Uploaded image for project: 'Apache Freemarker'
  1. Apache Freemarker
  2. FREEMARKER-125

ExtendedDecimalFormatParser ignores DecimalFormatSymbolsProvider

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Fixed
    • 2.3.28, 2.3.29
    • 2.3.30
    • engine
    • None

    Description

      We have customers that operate in multiple regions of Switzerland and use the locales de-CH, fr-CH and it-CH.

      The standard fr-CH number format changed when we upgraded from java 8 to java 11.

      old:
      1'000.00 (single quote as thousands separator and dot as decimal separator)
      new:
      1 000,00 (nonbreaking space as thousands separator and comma as decimal separator)

      To "fix" the issue we implemented a custom DecimalFormatSymbolsProvider to use the de-CH DecimalFormatSymbols for all swiss locales:

      public class SwissDecimalFormatSymbolsProvider extends DecimalFormatSymbolsProvider {
          @Override
          public Locale[] getAvailableLocales() {
              return new Locale[] {
                  Locale.forLanguageTag("de-CH"),
                  Locale.forLanguageTag("fr-CH"),
                  Locale.forLanguageTag("it-CH")
              };
          }
      
          @Override
          public DecimalFormatSymbols getInstance(Locale locale) {
              return new DecimalFormatSymbols(Locale.forLanguageTag("de-CH"));
          }
      }
      

      This works everywhere as expected except for when people use a "custom" freemarker number format.

      E.g.
      number?currency -> 1'000.00 CHF (correct de-CH DecimalFormatSymbols)
      number?string(",##0.00") -> 1 000,00 (wrong fr-CH DecimalFormatSymbols)

      I looked at the source code of the constructor of ExtendedDecimalFormatParser and DecimalFormatSymbols are "retrieved" by using the constructor of the DecimalFormatSymbols class.

      private ExtendedDecimalFormatParser(String formatString, Locale locale) {
          src = formatString;
          this.symbols = new DecimalFormatSymbols(locale);
      }
      

      This initialises DecimalFormatSymbols for the current locale ("fr-CH") instead of applying DecimalFormatSymbolsProviders.

      /**
       * Create a DecimalFormatSymbols object for the given locale.
       * This constructor can only construct instances for the locales
       * supported by the Java runtime environment, not for those
       * supported by installed
       * {@link java.text.spi.DecimalFormatSymbolsProvider DecimalFormatSymbolsProvider}
       * implementations. For full locale coverage, use the
       * {@link #getInstance(Locale) getInstance} method.
       * If the specified locale contains the {@link java.util.Locale#UNICODE_LOCALE_EXTENSION}
       * for the numbering system, the instance is initialized with the specified numbering
       * system if the JRE implementation supports it. For example,
       * <pre>
       * NumberFormat.getNumberInstance(Locale.forLanguageTag("th-TH-u-nu-thai"))
       * </pre>
       * This may return a {@code NumberFormat} instance with the Thai numbering system,
       * instead of the Latin numbering system.
       *
       * @param locale the desired locale
       * @exception NullPointerException if <code>locale</code> is null
       */
      public DecimalFormatSymbols( Locale locale ) {
          initialize( locale );
      }

      Attachments

        Activity

          People

            Unassigned Unassigned
            aschi Adrian Schmid
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: