diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/LocaleModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/LocaleModuleBuiltins.java index 05acd0da36..79460e1768 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/LocaleModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/LocaleModuleBuiltins.java @@ -126,9 +126,15 @@ static PDict localeconv() { Locale numericLocale = currentPythonLocale.category(LC_NUMERIC); NumberFormat numericLocaleNumFormat = NumberFormat.getInstance(numericLocale); DecimalFormatSymbols decimalFormatSymbols = getDecimalFormatSymbols(numericLocale, numericLocaleNumFormat); + char decimalPoint = decimalFormatSymbols.getDecimalSeparator(); + char thousandsSep = decimalFormatSymbols.getGroupingSeparator(); + // Align with CPython behaviour for locales like ru_RU where Java may use NBSP + if ("ru".equals(numericLocale.getLanguage()) && thousandsSep == '\u00A0') { + thousandsSep = '\u202F'; + } - dict.put("decimal_point", TruffleString.fromCodePointUncached(decimalFormatSymbols.getDecimalSeparator(), TS_ENCODING)); - dict.put("thousands_sep", TruffleString.fromCodePointUncached(decimalFormatSymbols.getGroupingSeparator(), TS_ENCODING)); + dict.put("decimal_point", TruffleString.fromCodePointUncached(decimalPoint, TS_ENCODING)); + dict.put("thousands_sep", TruffleString.fromCodePointUncached(thousandsSep, TS_ENCODING)); dict.put("grouping", getDecimalFormatGrouping(language, numericLocaleNumFormat)); // LC_MONETARY @@ -136,11 +142,16 @@ static PDict localeconv() { NumberFormat monetaryNumFormat = NumberFormat.getInstance(monetaryLocale); Currency currency = monetaryNumFormat.getCurrency(); decimalFormatSymbols = getDecimalFormatSymbols(monetaryLocale, monetaryNumFormat); + char monDecimalPoint = decimalFormatSymbols.getMonetaryDecimalSeparator(); + char monThousandsSep = decimalFormatSymbols.getGroupingSeparator(); + if ("ru".equals(monetaryLocale.getLanguage()) && monThousandsSep == '\u00A0') { + monThousandsSep = '\u202F'; + } dict.put("int_curr_symbol", toTruffleStringUncached(decimalFormatSymbols.getInternationalCurrencySymbol())); dict.put("currency_symbol", toTruffleStringUncached(decimalFormatSymbols.getCurrencySymbol())); - dict.put("mon_decimal_point", TruffleString.fromCodePointUncached(decimalFormatSymbols.getMonetaryDecimalSeparator(), TS_ENCODING)); - dict.put("mon_thousands_sep", TruffleString.fromCodePointUncached(decimalFormatSymbols.getGroupingSeparator(), TS_ENCODING)); + dict.put("mon_decimal_point", TruffleString.fromCodePointUncached(monDecimalPoint, TS_ENCODING)); + dict.put("mon_thousands_sep", TruffleString.fromCodePointUncached(monThousandsSep, TS_ENCODING)); dict.put("mon_grouping", getDecimalFormatGrouping(language, monetaryNumFormat)); // TODO: reasonable default, but not the current locale setting dict.put("positive_sign", ""); diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/formatting/IntegerFormatter.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/formatting/IntegerFormatter.java index d8b79363e7..401b4edea5 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/formatting/IntegerFormatter.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/formatting/IntegerFormatter.java @@ -14,6 +14,8 @@ import com.oracle.graal.python.nodes.ErrorMessages; import com.oracle.graal.python.nodes.PRaiseNode; +import com.oracle.graal.python.runtime.PythonContext; +import com.oracle.graal.python.runtime.locale.PythonLocale; import com.oracle.graal.python.runtime.formatting.FormattingBuffer.StringFormattingBuffer; import com.oracle.graal.python.runtime.formatting.InternalFormat.Spec; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; @@ -117,9 +119,8 @@ public IntegerFormatter format(BigInteger value) { break; case 'n': - // Locale-sensitive version of d-format - format_d(value); - setGroupingAndGroupSize(getCurrentDecimalFormat()); + // Locale-sensitive version of d-format using current Python locale + format_n(value); break; default: @@ -176,7 +177,8 @@ void format_d(BigInteger value) { */ void format_n(BigInteger value) { String number; - NumberFormat nf = NumberFormat.getNumberInstance(); + NumberFormat nf = NumberFormat.getNumberInstance( + PythonContext.get(null).getCurrentLocale().category(PythonLocale.LC_NUMERIC)); if (value.signum() < 0) { // Negative value: deal with sign and base, and convert magnitude. negativeSign(null); @@ -194,7 +196,8 @@ void format_n(BigInteger value) { */ void format_n(int value) { String number; - NumberFormat nf = NumberFormat.getNumberInstance(); + NumberFormat nf = NumberFormat.getNumberInstance( + PythonContext.get(null).getCurrentLocale().category(PythonLocale.LC_NUMERIC)); if (value < 0) { // Negative value: deal with sign and base, and convert magnitude. negativeSign(null); @@ -349,8 +352,7 @@ public IntegerFormatter format(int value) { case 'n': // Locale-sensitive version of d-format - format_d(value); - setGroupingAndGroupSize(getCurrentDecimalFormat()); + format_n(value); break; default: diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/locale/PythonLocale.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/locale/PythonLocale.java index 48b9186fbf..532cc91bfa 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/locale/PythonLocale.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/locale/PythonLocale.java @@ -113,6 +113,7 @@ public PythonLocale(Locale displayLocale, Locale formatLocale) { public Locale category(int category) { return switch (category) { case LC_COLLATE, LC_CTYPE, LC_MESSAGES -> formatLocale; + case LC_MONETARY, LC_NUMERIC, LC_TIME -> displayLocale; default -> displayLocale; }; }