Tapestry 5
  1. Tapestry 5
  2. TAP5-211

Client-side validation of numeric user input does not take into account the user's locale which causes spurious client- and server-side exceptions when users enter numbers "naturally"

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 5.1.0.0
    • Fix Version/s: 5.1.0.1
    • Component/s: None
    • Labels:
      None

      Description

      Localization support for pages and messages is great in Tapestry but it lacks support for localization of input values because the translators don't have support for it. It would be great if users could just enter numbers etc. in their respective locale, e.g. use ',' instead of '.' to seperate decimal places from the integer part, out of the box.

      1. tapestry-locale-float-validation.diff
        19 kB
        Joakim Olsson
      2. LocalizedTranslatorSource.zip
        2 kB
        Ulrich Stärk
      3. TAPESTRY-2457.txt
        16 kB
        Ulrich Stärk

        Activity

        Hide
        Ulrich Stärk added a comment -

        This patch adds support for localized translators by extending the Translator interface. It also introduces a new SymbolConstant tapestry.localized-translators which defaults to false to indicate whether localized translators should be used or not. The FloatTranslator and DoubleTranslator have been updated to parse and display floating point numbers in the client's locale (if so desired). FieldValidationSupportImpl has been altered to use the old (not localized) translators or if tapestry.localized-translators is set to true, to use the localized versions of the translators.

        Show
        Ulrich Stärk added a comment - This patch adds support for localized translators by extending the Translator interface. It also introduces a new SymbolConstant tapestry.localized-translators which defaults to false to indicate whether localized translators should be used or not. The FloatTranslator and DoubleTranslator have been updated to parse and display floating point numbers in the client's locale (if so desired). FieldValidationSupportImpl has been altered to use the old (not localized) translators or if tapestry.localized-translators is set to true, to use the localized versions of the translators.
        Hide
        Ville Virtanen added a comment -

        This really should be corrected. Please let user override default translators, as this would fix the problem.

        Howard: is there good reason why developers aren't allowed to override default translators?

        Show
        Ville Virtanen added a comment - This really should be corrected. Please let user override default translators, as this would fix the problem. Howard: is there good reason why developers aren't allowed to override default translators?
        Hide
        Howard M. Lewis Ship added a comment -

        There isn't a need, generally, and if there is, you can contribute your own translators. At issue is the fact that neither Tapestry not Prototype provides a JavaScript equivalent of Locale or Format, meaning that there's a strong possibility that localized number parsing on the server side will not be expressed on the client side (that is, the client side will accept one format, the server side enforce a different format).

        So, we have to come up with a way for the client side to have parsing functions that match the server side, w.r.t. seperator characters (such as ',' in English) and decimal point ('.').

        Show
        Howard M. Lewis Ship added a comment - There isn't a need, generally, and if there is, you can contribute your own translators. At issue is the fact that neither Tapestry not Prototype provides a JavaScript equivalent of Locale or Format, meaning that there's a strong possibility that localized number parsing on the server side will not be expressed on the client side (that is, the client side will accept one format, the server side enforce a different format). So, we have to come up with a way for the client side to have parsing functions that match the server side, w.r.t. seperator characters (such as ',' in English) and decimal point ('.').
        Hide
        Ulrich Stärk added a comment -

        The majority of the world (see http://en.wikipedia.org/wiki/Decimal_separator#Examples_of_use) is using the ',' char as a seperator and you are saying there is no general need?

        Sure, for a simple form on some page you can just provide your own Translator for the respective field. But if you are using components that rely on translators from the TranslatorSource service (like BeanEditForm) you can't just contribute your own translators, you'll also have to replace the TranslatorSource with an implementation that uses the current user's locale, so a workaround is everything else but trivial. And then there is still the client side validation issue.

        So there are two things that need to be adressed:

        1. We either need to have a TranslatorSource that takes into account the current user's locale or extend the Translator interface
        2. We need a client side parsing function that matches the server side.

        Dojo (http://api.dojotoolkit.org/jsdoc/dojo/1.2/dojo.number) has a number parser/formatter that can handle different locales, maybe we can borrow something from there.

        Show
        Ulrich Stärk added a comment - The majority of the world (see http://en.wikipedia.org/wiki/Decimal_separator#Examples_of_use ) is using the ',' char as a seperator and you are saying there is no general need? Sure, for a simple form on some page you can just provide your own Translator for the respective field. But if you are using components that rely on translators from the TranslatorSource service (like BeanEditForm) you can't just contribute your own translators, you'll also have to replace the TranslatorSource with an implementation that uses the current user's locale, so a workaround is everything else but trivial. And then there is still the client side validation issue. So there are two things that need to be adressed: 1. We either need to have a TranslatorSource that takes into account the current user's locale or extend the Translator interface 2. We need a client side parsing function that matches the server side. Dojo ( http://api.dojotoolkit.org/jsdoc/dojo/1.2/dojo.number ) has a number parser/formatter that can handle different locales, maybe we can borrow something from there.
        Hide
        Ulrich Stärk added a comment -

        Here is a localized TranslatorSource and a localized double translator I wrote, configure them like this in your module:

        public static LocalizedTranslatorSource buildLocalizedTranslatorSource(
        @Inject @Symbol("tapestry.supported-locales") final String supportedLocales,
        @InjectService("ThreadLocale") ThreadLocale threadLocale)
        {
        HashMap<Locale, Collection<Translator>> configuration = new HashMap<Locale, Collection<Translator>>();

        for (String locale : supportedLocales.split(","))

        { Locale l = new Locale(locale); Collection<Translator> s = new HashSet<Translator>(); s.add(new LocalizedDoubleTranslator(l)); s.add(new StringTranslator()); s.add(new ByteTranslator()); s.add(new IntegerTranslator()); s.add(new LongTranslator()); s.add(new FloatTranslator()); s.add(new ShortTranslator()); configuration.put(l, s); }

        return new LocalizedTranslatorSource(configuration, threadLocale);
        }

        public static void contributeAliasOverrides(Configuration<AliasContribution> configuration,
        @InjectService("LocalizedTranslatorSource")
        LocalizedTranslatorSource localizedTranslatorSource)

        { configuration.add(AliasContribution.create( TranslatorSource.class, localizedTranslatorSource)); }
        Show
        Ulrich Stärk added a comment - Here is a localized TranslatorSource and a localized double translator I wrote, configure them like this in your module: public static LocalizedTranslatorSource buildLocalizedTranslatorSource( @Inject @Symbol("tapestry.supported-locales") final String supportedLocales, @InjectService("ThreadLocale") ThreadLocale threadLocale) { HashMap<Locale, Collection<Translator>> configuration = new HashMap<Locale, Collection<Translator>>(); for (String locale : supportedLocales.split(",")) { Locale l = new Locale(locale); Collection<Translator> s = new HashSet<Translator>(); s.add(new LocalizedDoubleTranslator(l)); s.add(new StringTranslator()); s.add(new ByteTranslator()); s.add(new IntegerTranslator()); s.add(new LongTranslator()); s.add(new FloatTranslator()); s.add(new ShortTranslator()); configuration.put(l, s); } return new LocalizedTranslatorSource(configuration, threadLocale); } public static void contributeAliasOverrides(Configuration<AliasContribution> configuration, @InjectService("LocalizedTranslatorSource") LocalizedTranslatorSource localizedTranslatorSource) { configuration.add(AliasContribution.create( TranslatorSource.class, localizedTranslatorSource)); }
        Hide
        Andreas Andreou added a comment -

        Regarding the client side if this, i too used parts of dojo when doing tacos-jquery...

        In http://tacos.svn.sourceforge.net/viewvc/tacos/tacos-4.1/trunk/tacos-jquery/src/js/tacos-jquery-js/tap-jquery1.2.1.js?view=markup
        the most important parts are tapestry.form.validation.FORMAT_TABLE (line 1227, holds info for each locale ) and the various validation methods in tapestry.form.validation (line 786)

        Show
        Andreas Andreou added a comment - Regarding the client side if this, i too used parts of dojo when doing tacos-jquery... In http://tacos.svn.sourceforge.net/viewvc/tacos/tacos-4.1/trunk/tacos-jquery/src/js/tacos-jquery-js/tap-jquery1.2.1.js?view=markup the most important parts are tapestry.form.validation.FORMAT_TABLE (line 1227, holds info for each locale ) and the various validation methods in tapestry.form.validation (line 786)
        Hide
        Joakim Olsson added a comment - - edited

        I just attached my crude implementation of locale-aware double- and float-translators. The implementation also contains client-side locale-aware validation by sending the regular expression used to validate decimal numbers in the Tapestry.Init-call.

        Maybe it can be of any use when creating a "real" solution to the problem.

        Show
        Joakim Olsson added a comment - - edited I just attached my crude implementation of locale-aware double- and float-translators. The implementation also contains client-side locale-aware validation by sending the regular expression used to validate decimal numbers in the Tapestry.Init-call. Maybe it can be of any use when creating a "real" solution to the problem.
        Hide
        Howard M. Lewis Ship added a comment -

        The biggest problem is the use of thousands-seperators ("," in the US, "." in many other places) and the decimal point ("." in the US, "," in many other places).

        Switched from using Number.toString() and Long.parseLong(), Integer.parseInteger(), etc. to something more powerful, based on localized NumberFormats.

        In the attitude of "be gracious in what you accept and precise in what you emit" ... the thousands-seperator is simply ignored on the client side.

        Show
        Howard M. Lewis Ship added a comment - The biggest problem is the use of thousands-seperators ("," in the US, "." in many other places) and the decimal point ("." in the US, "," in many other places). Switched from using Number.toString() and Long.parseLong(), Integer.parseInteger(), etc. to something more powerful, based on localized NumberFormats. In the attitude of "be gracious in what you accept and precise in what you emit" ... the thousands-seperator is simply ignored on the client side.

          People

          • Assignee:
            Howard M. Lewis Ship
            Reporter:
            Ulrich Stärk
          • Votes:
            22 Vote for this issue
            Watchers:
            10 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development