Globalization API Feedback - moar!

Nebojša Ćirić cira at google.com
Wed Nov 23 12:57:06 PST 2011


Similar approach was proposed (with locale as a top object, others under
it) and I have nothing against it, but there are some issues with your
approach:

(code == localeID)

1. An implementation may support NumberFormat for localeID x, but not
support DateFormat for x (it would need to do a fallback to less specific
one, or default). That's why we have supportedLocaleOf method on each
object.

2. How do you convey status of option/locale resolution to the developer?
Which options were resolved and to what value (say I ask for 'islamic'
calendar, but we only have 'gregory' for a given locale). In our current
proposal we expose resolvedOptions accessor on i.e. DateTimeFormat object
instance that has 'calendar' property, so a developer can decide what to do.

3. This approach would require internal caching of
collator/dateformatter/numberformatter objects.

23. новембар 2011. 12.09, Nicholas C. Zakas
<standards at nczconsulting.com>је написао/ла:

> After meeting with Norbert to discuss the use cases and design decision
> rationale, I've come to a different understanding of the goals of the
> globalization API. Some things I learned:
>
> 1. Augmenting native types with some default locale support may be
> dangerous. Consider the case where a single web page displays two modules
> with different locales. Which one wins? Therefore, "default" locale
> behavior for native types is impractical.
> 2. Locale information is most frequently used for formatting numbers and
> dates as well as comparing strings. The locale information doesn't permeate
> the entire execution context.
> 3. Developers are likely to want to define locale information once and
> then reuse that multiple times through a script.
>
> Given this, I'd like to propose an alternate approach to the one currently
> taken in the API and also different from my initial email. It goes like
> this:
>
> Have a single, top-level type called Locale defined as:
>
>    function Locale(code){
>
>        //whatever has to happen to process the code
>
>        this.code = code;
>    }
>
>    /*
>     * Determine if a locale is supported.
>     * @param code The code to check.
>     * @return True if supported, false if not.
>     */
>    Locale.isLocaleSupported = function(code){
>        ...
>    };
>
>    /*
>     * Replaces supportedLocalesOf
>     * @param code The code to check.
>     * @return Array of supported locales.
>     */
>    Locale.getSupportedLocales = function(code){
>        ...
>    };
>
>    /*
>     * Replaces Globalization.Collator
>     * @param a The first item.
>     * @param b The second item.
>     * @param options (Optional) The options to use when comparing.
>     * @return -1 if a comes before b, 0 if they're equal, 1 otherwise
>     */
>    Locale.prototype.compare = function(a, b, options){
>        ...
>    };
>
>    /*
>     * Replaces Globalization.NumberFormat
>     * @param format A pattern format string for outputting the number.
>     * @param value The value to format.
>     * @return The number formatted as a string.
>     */
>     Locale.prototype.formatNumber = function(format, value){
>        ...
>    };
>
>    /*
>     * Replaces Globalization.DateFormat
>     * @param format A pattern format string for outputting the date.
>     * @param value The date to format.
>     * @return The number formatted as a string.
>     */
>    Locale.prototype.formatDate = function(format, value){
>        ...
>    };
>
> You would then be able to create a single Locale instance and have that be
> used in your script. If the constructor is used without an argument, then
> default locale information is used:
>
>    var locale = new Locale();
>
> If you provide a code, then that is used:
>
>    var locale = new Locale("en-us");
>
> If you provide multiple codes, then the first supported one is used:
>
>    var locale = new Locale(["en-us", "en-gb"]);
>
> Then, you can use that locale information for the other operations you
> want to do:
>
>    locale.formatDate("DMYs-short"**, new Date());
>    locale.formatNumber("##.##", 55);
>    locale.compare("foo", "bar");
>
> By the way, not saying this is the format pattern string that should be
> used, it's just for discussion.
>
> I like having a single object to deal with instead of multiple for
> everything the API is trying to do. It seems a lot more intuitive than
> needing to manage a LocaleList that is passed into new instances of
> NumberFormat and DateFormat all the time (that's a bunch of housekeeping
> for developers).
>
> Thoughts?
>
> -Nicholas
>
>
>
>
> On 11/21/2011 11:12 AM, Nicholas C. Zakas wrote:
>
>> As promised, more verbose feedback for the Globalization API. My general
>> feeling is that the API is overly verbose for what it's doing. I'll state
>> my bias up front: I'm not a fan of introducing a bunch of new types to
>> handle formatting. I'd much rather have additional methods that perform
>> formatting on existing objects. My feedback is mostly about eliminating the
>> new constructors - which has an added bonus of eliminating the
>> Globalization namespace because there would be only one constructor left:
>> Collator.
>>
>> 1. LocaleList
>>
>> I'm not sure why this type is necessary. I don't believe that locale
>> resolution is an expensive operation, and even if it is, I'd expect the
>> implementation to cache the results of such resolution for later use. I'd
>> just leave this as an internal construct and instruct developers to use
>> arrays all the time.
>>
>> 2. supportedLocalesOf
>>
>> I find this method name strange - I've read it several times and am still
>> not sure I fully understand what it does. Perhaps "getSupportedLocales()"
>> is a better name for this method? (I always prefer methods begin with
>> verbs.)
>>
>> 3. NumberFormat
>>
>> Number formatting seems simple enough that it could just be added as a
>> series of methods on Number.prototype. The three types of formatting
>> (currency, decimal, percent) could each have their own method. Currency
>> formatting has relatively few options to specify, so it's method can be:
>>
>>    /*
>>     * Formats the number as if it were currency
>>     * @param code Currency code, e.g., "EUR"
>>     * @param type (Optional) The way to format the currency code, "code",
>> "symbol" (default),
>>     * @param locales - (Optional) Array of locales to use.
>>     */
>>    Number.prototype.**toCurrencyString = function(code, type, locales) {
>>        ...
>>    };
>>
>>    var num = 500;
>>    console.log(num.**toCurrencyCode("EUR", "code"));    //"EUR 500.00"
>>
>>
>> Decimal and percent formatting options are slightly different in that
>> they include significant digits options. For that, I prefer to use a
>> formatting string rather than the multitude of optional properties as
>> currently defined (see http://www.exampledepot.com/**
>> egs/java.text/FormatNum.html<http://www.exampledepot.com/egs/java.text/FormatNum.html>).
>> The formatting string indicates must-have digits as 0 and optional digits
>> as #, allowing you to very succinctly specify how you want your number to
>> be output. For example:
>>
>>    /*
>>     * Formats the number as a decimal string.
>>     * @param format Format string indicating max/min significant digits
>>     * @param locales (Optional) Array of locales to use.
>>     */
>>    Number.prototype.**toDecimalString = function(format, locales){
>>        ...
>>    };
>>
>>    /*
>>     * Formats the number as a percent string.
>>     * @param format Format string indicating max/min significant digits
>>     * @param locales (Optional) Array of locales to use.
>>     */
>>    Number.prototype.**toPercentString = function(format, locales){
>>        ...
>>    };
>>
>>    var num = 1234.567;
>>    console.log(**numtoDecimalString("000##.##")**); "01234.57"
>>
>> 4. DateTimeFormat
>>
>> As with NumberFormat, it seems like this could more succinctly be
>> implemented as a method on Date.prototype. As its easiest:
>>
>>    /*
>>     * Format a date
>>     * @param options The already-defined options for DateTimeFormat
>>     * @param locales (Optional) Array of locales to use.
>>     */
>>    Date.prototype.toFormatString = function(options, locales){
>>        ...
>>    };
>>
>> In an ideal world, I'd like to see options overloaded so it can be an
>> options object as specified now or a formatting string. I understand that
>> there was a sentiment against formatting strings due to their limitations
>> and edge case errors. However, I'd like to point out that any
>> internationalized web application is highly likely to already be using
>> formatting strings for dates, since this is pretty much how every other
>> language handles date formatting. That means supporting format strings in
>> JavaScript would allow application developers to reuse the settings they
>> already have. As it stands now, you'd need to create two different ways of
>> formatting dates for a web app: one for your server-side language and one
>> for your client-side language (until the day everything is running on
>> Node.js, of course). I'd prefer my client-side code to reuse settings and
>> configuration that the server-side code uses, otherwise I end up with two
>> very different pieces of code doing the exact same thing, and there be
>> dragons.
>>
>> -Nicholas
>>
>
> ______________________________**_________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/**listinfo/es-discuss<https://mail.mozilla.org/listinfo/es-discuss>
>



-- 
Nebojša Ćirić
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20111123/8735370e/attachment-0001.html>


More information about the es-discuss mailing list