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). 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
[email protected]
https://mail.mozilla.org/listinfo/es-discuss