Author: j...@google.com
Date: Wed May 20 21:41:21 2009
New Revision: 5450

Modified:
    trunk/user/src/com/google/gwt/i18n/client/NumberFormat.java
    trunk/user/test/com/google/gwt/i18n/client/NumberFormat_ar_Test.java

Log:
Allow an app to force use of latin digits/separators instead
of localized digits.

Patch by: jat
Review by: andreasst


Modified: trunk/user/src/com/google/gwt/i18n/client/NumberFormat.java
==============================================================================
--- trunk/user/src/com/google/gwt/i18n/client/NumberFormat.java (original)
+++ trunk/user/src/com/google/gwt/i18n/client/NumberFormat.java Wed May 20  
21:41:21 2009
@@ -306,29 +306,53 @@
   */
  public class NumberFormat {

-  // Sets of constants as defined for the default locale.
-  private static final NumberConstants defaultNumberConstants =  
LocaleInfo.getCurrentLocale().getNumberConstants();
+  // Sets of constants as defined for the current locale from CLDR.
+  protected static final NumberConstants localizedNumberConstants =  
LocaleInfo.getCurrentLocale().getNumberConstants();
+
+  /**
+   * Current NumberConstants interface to use, see
+   * {...@link #setForcedLatinDigits(boolean)} for changing it.
+   */
+  protected static NumberConstants defaultNumberConstants =  
localizedNumberConstants;
+
+  // Cached instances of standard formatters.
+  private static NumberFormat cachedCurrencyFormat;
+  private static NumberFormat cachedDecimalFormat;
+  private static NumberFormat cachedPercentFormat;
+  private static NumberFormat cachedScientificFormat;
+
+  // Number constants mapped to use latin digits/separators.
+  private static NumberConstants latinNumberConstants = null;
+
+  // Localized characters for dot and comma in number patterns, used to  
produce
+  // the latin mapping for arbitrary locales.  Any separator not in either  
of
+  // these strings will be mapped to non-breaking space (U+00A0).
+  private static final String LOCALIZED_COMMA_EQUIVALENTS  
= ".\u060C\u066B\u3001\uFE10\uFE11\uFE50\uFE51\uFF0C\uFF64";
+  private static final String LOCALIZED_DOT_EQUIVALENTS  
= ".\u2024\u3002\uFE12\uFE52\uFF0E\uFF61";

    // Constants for characters used in programmatic (unlocalized) patterns.
-  private static final char PATTERN_ZERO_DIGIT = '0';
-  private static final char PATTERN_GROUPING_SEPARATOR = ',';
+  private static final char CURRENCY_SIGN = '\u00A4';
    private static final char PATTERN_DECIMAL_SEPARATOR = '.';
-  private static final char PATTERN_PER_MILLE = '\u2030';
-  private static final char PATTERN_PERCENT = '%';
    private static final char PATTERN_DIGIT = '#';
-  private static final char PATTERN_SEPARATOR = ';';
    private static final char PATTERN_EXPONENT = 'E';
+  private static final char PATTERN_GROUPING_SEPARATOR = ',';
    private static final char PATTERN_MINUS = '-';
-  private static final char CURRENCY_SIGN = '\u00A4';
-  private static final char QUOTE = '\'';
+  private static final char PATTERN_PER_MILLE = '\u2030';
+  private static final char PATTERN_PERCENT = '%';
+  private static final char PATTERN_SEPARATOR = ';';
+  private static final char PATTERN_ZERO_DIGIT = '0';

-  // Cached instances of standard formatters.
-  private static NumberFormat cachedDecimalFormat;
-  private static NumberFormat cachedScientificFormat;
-  private static NumberFormat cachedPercentFormat;
-  private static NumberFormat cachedCurrencyFormat;
+  private static final char QUOTE = '\'';

    /**
+   * @return true if all new NumberFormat instances will use latin digits
+   *     and related characters rather than the localized ones.
+   */
+  public static boolean forcedLatinDigits() {
+    return defaultNumberConstants != localizedNumberConstants;
+  }
+
+  /**
     * Provides the standard currency format for the default locale.
     *
     * @return a <code>NumberFormat</code> capable of producing and consuming
@@ -341,7 +365,7 @@
      }
      return cachedCurrencyFormat;
    }
-
+
    /**
     * Provides the standard currency format for the default locale using a
     * specified currency.
@@ -427,49 +451,184 @@
      return cachedScientificFormat;
    }

-  // Locale specific symbol collection.
-  private final NumberConstants numberConstants;
+  /**
+   * Specify whether all new NumberFormat instances will use latin digits
+   * and related characters rather than the localized ones.
+   *
+   * @param useLatinDigits true if latin digits/etc should be used, false  
if
+   *    localized digits/etc should be used.
+   */
+  public static void setForcedLatinDigits(boolean useLatinDigits) {
+    // Invalidate cached formats if changing
+    if (useLatinDigits != forcedLatinDigits()) {
+      cachedCurrencyFormat = null;
+      cachedDecimalFormat = null;
+      cachedPercentFormat = null;
+      cachedScientificFormat = null;
+    }
+    if (useLatinDigits) {
+      if (latinNumberConstants == null) {
+        latinNumberConstants = createLatinNumberConstants(
+            localizedNumberConstants);
+      }
+      defaultNumberConstants = latinNumberConstants;
+    } else {
+      defaultNumberConstants = localizedNumberConstants;
+    }
+  }

-  private int maximumIntegerDigits = 40;
-  private int minimumIntegerDigits = 1;
-  private int maximumFractionDigits = 3; // invariant, >=  
minFractionDigits.
-  private int minimumFractionDigits = 0;
-  private int minExponentDigits;
+  /**
+   * Create a delocalized NumberConstants instance from a localized one.
+   *
+   * @param orig localized NumberConstants instance
+   * @return NumberConstants instance using latin digits/etc
+   */
+  protected static NumberConstants createLatinNumberConstants(final  
NumberConstants orig) {
+    final String groupingSeparator = remapSeparator(
+        orig.groupingSeparator());
+    final String decimalSeparator = remapSeparator(
+        orig.decimalSeparator());
+    final String monetaryGroupingSeparator = remapSeparator(
+        orig.monetaryGroupingSeparator());
+    final String monetarySeparator = remapSeparator(
+        orig.monetarySeparator());
+    return new NumberConstants() {
+      public String currencyPattern() {
+        return orig.currencyPattern();
+      }
+
+      public String decimalPattern() {
+        return orig.decimalPattern();
+      }
+
+      public String decimalSeparator() {
+        return decimalSeparator;
+      }
+
+      public String defCurrencyCode() {
+        return orig.defCurrencyCode();
+      }
+
+      public String exponentialSymbol() {
+        return orig.exponentialSymbol();
+      }
+
+      public String groupingSeparator() {
+        return groupingSeparator;
+      }
+
+      public String infinity() {
+        return orig.infinity();
+      }
+
+      public String minusSign() {
+        return orig.minusSign();
+      }
+
+      public String monetaryGroupingSeparator() {
+        return monetaryGroupingSeparator;
+      }
+
+      public String monetarySeparator() {
+        return monetarySeparator;
+      }
+
+      public String notANumber() {
+        return orig.notANumber();
+      }
+
+      public String percent() {
+        return orig.percent();
+      }
+
+      public String percentPattern() {
+        return orig.percentPattern();
+      }
+
+      public String perMill() {
+        return orig.perMill();
+      }
+
+      public String plusSign() {
+        return orig.plusSign();
+      }
+
+      public String scientificPattern() {
+        return orig.scientificPattern();
+      }
+
+      public String zeroDigit() {
+        return "0";
+      }
+    };
+  }

-  private String positivePrefix = "";
-  private String positiveSuffix = "";
-  private String negativePrefix = "-";
-  private String negativeSuffix = "";
+  /**
+   * Remap a localized separator to an equivalent latin one.
+   *
+   * @param separator
+   * @return delocalized separator character
+   */
+  protected static String remapSeparator(String separator) {
+    char ch = separator.length() > 0 ? separator.charAt(0) : 0xFFFF;
+    if (LOCALIZED_DOT_EQUIVALENTS.indexOf(ch) >= 0) {
+      return ".";
+    }
+    if (LOCALIZED_COMMA_EQUIVALENTS.indexOf(ch) >= 0) {
+      return ",";
+    }
+    return "\u00A0";
+  }

-  // The multiplier for use in percent, per mille, etc.
-  private int multiplier = 1;
+  // The currency code.
+  private final String currencyCode;

-  // The number of digits between grouping separators in the integer
-  // portion of a number.
-  private int groupingSize = 3;
+  // Currency setting.
+  private final String currencySymbol;

    // Forces the decimal separator to always appear in a formatted number.
    private boolean decimalSeparatorAlwaysShown = false;

+  // The number of digits between grouping separators in the integer
+  // portion of a number.
+  private int groupingSize = 3;
+
    private boolean isCurrencyFormat = false;
+
+  private int maximumFractionDigits = 3; // invariant, >=  
minFractionDigits.
+  private int maximumIntegerDigits = 40;
+  private int minExponentDigits;
+  private int minimumFractionDigits = 0;
+  private int minimumIntegerDigits = 1;

-  // True to force the use of exponential (i.e. scientific) notation.
-  private boolean useExponentialNotation = false;
+  // The multiplier for use in percent, per mille, etc.
+  private int multiplier = 1;

-  // Currency setting.
-  private final String currencySymbol;
+  private String negativePrefix = "-";

-  // The currency code.
-  private final String currencyCode;
+  private String negativeSuffix = "";
+
+  // Locale specific symbol collection.
+  private final NumberConstants numberConstants;

    // The pattern to use for formatting and parsing.
    private final String pattern;

+  private String positivePrefix = "";
+
+  private String positiveSuffix = "";
+
+  // True to force the use of exponential (i.e. scientific) notation.
+  private boolean useExponentialNotation = false;
+
    /**
     * Constructs a format object based on the specified settings.
     *
     * @param numberConstants the locale-specific number constants to use  
for this
-   *          format
+   *          format -- **NOTE** subclasses passing their own instance here
+   *          should pay attention to {...@link #forcedLatinDigits()} and  
remap
+   *          localized symbols using
+   *          {...@link #createLatinNumberConstants(NumberConstants)}
     * @param pattern pattern that specify how number should be formatted
     * @param cdata currency data that should be used
     * @param userSuppliedPattern true if the pattern was supplied by the  
user

Modified:  
trunk/user/test/com/google/gwt/i18n/client/NumberFormat_ar_Test.java
==============================================================================
--- trunk/user/test/com/google/gwt/i18n/client/NumberFormat_ar_Test.java        
 
(original)
+++ trunk/user/test/com/google/gwt/i18n/client/NumberFormat_ar_Test.java        
 
Wed May 20 21:41:21 2009
@@ -47,6 +47,20 @@
          fmt.format(-314.0));
    }

+  public void testForceLatin() {
+    assertFalse(NumberFormat.forcedLatinDigits());
+    NumberFormat.setForcedLatinDigits(true);
+    assertTrue(NumberFormat.forcedLatinDigits());
+    NumberFormat decLatin = NumberFormat.getDecimalFormat();
+    assertEquals("1\u00A0003,14", decLatin.format(1003.14));
+    assertEquals("1\u00A0003,14-", decLatin.format(-1003.14));
+    NumberFormat.setForcedLatinDigits(false);
+    assertFalse(NumberFormat.forcedLatinDigits());
+    assertEquals("3,14", decLatin.format(3.14));
+    NumberFormat decArabic = NumberFormat.getDecimalFormat();
+    assertEquals("\u0663\u066B\u0661\u0664", decArabic.format(3.14));
+  }
+
    public void testParse() {
      NumberFormat fmt = NumberFormat.getDecimalFormat();
      assertEquals(3.14, fmt.parse("\u0663\u066B\u0661\u0664"));

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Google Web Toolkit Contributors" group.
To post to this group, send email to 
Google-Web-Toolkit-Contributors@googlegroups.com
To unsubscribe from this group, send email to 
google-web-toolkit-contributors+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/Google-Web-Toolkit-Contributors?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to