28. новембар 2011. 11.27, Nicholas C. Zakas <[email protected]>је написао/ла:
> On 11/28/2011 9:15 AM, Nebojša Ćirić wrote: > > It's my fault - I read "discussed with Norbert" as if you and Norbert > agreed on this approach. > > No worries - email is hard. :) > > > > We are essentially choosing beween two approaches: > > 1. Create an object, query its properties, use object methods (original > approach) > 2. Create Locale object, call various methods like isSupportedXXX, if > service is supported use formatYYY or compare > > They are very similar in what the user has to do (query capabilites, call > formatters) to get the final result, so I don't think we would lose any > functionality picking any of those. > > With 1. we might end up having lots of isSupportedDate, > isSupportedNumber... after couple of iterations of adding new features > (like segmentation, calendars, spell check...), but if we follow the same > naming style I don't see a problem with that. > > Another approach would be to have a single isSupported() method with > constants that you pass in. That limits the overall API size while still > allowing developers to query capabilities. The DOM has something similar, > though I think the globalization use case is much more appropriate: > http://www.w3.org/TR/DOM-Level-3-Core/core.html#DOMFeatures > What would be harder for a third party developer to extend: isSupported('x') or isSupportedX() This in case they wanted to provide a service which native implementation doesn't support (yet). > > As for the namespace issue, I don't see much difference between Locale > and Globalization. We discussed Modules on the other thread and came up > with: > > Object.system.load('@g11n', callback()) {} > > or synchronous call > > var global = Object.system.load('@g11n') { > return __Globalization__; > } > > This would become module global import '@g11n' in the future. This > approach eliminates the need of finding proper name for the namespace (and > possibly for Locale()?). > > There's a difference between creating a new native type vs. creating a > namespace. The Locale approach creates a single top-level type and no other > constructors. The current approach, Globalization.*, uses Globalization > only as a namespace and has constructors hanging off of it - this isn't > something that's currently done in ECMAScript. > > > Thank you for helping out. Your proposal is exactly what we need at this > point - to help us refine our work and make it palatable to TC39 members :). > > My pleasure! > > > > 24. новембар 2011. 16.47, Nicholas C. Zakas <[email protected]>је > написао/ла: > >> Again, my apologies - I didn't mean to imply that Norbert agreed with any >> of this, just that a few ideas have been more solidified in my mind after >> speaking with him. >> >> As a web developer who has built large-scale web sites that have been >> internationalized to dozens of countries, my main purpose in contributing >> to this discussion is to provide feedback on what I would have liked to see >> in such an API to make it useful to me. >> >> The current proposal doesn't feel very JavaScript-like, and so I've been >> trying to offer alternatives that make it more JavaScript-like and, >> therefore, more likely to be used by more developers. I'm a bit concerned >> that design decisions seem to have been guided by considering the most >> complex use cases instead of the most common. >> >> It is my opinion (and I can only speak for myself) that a single object >> to encompass would represent a better API for JavaScript than adding a >> namespace, which hasn't been done to this point, and several new types, all >> of which just do one thing. That's a very Java-like approach, and I think >> JavaScript deserves better. >> >> As I told Norbert, I'm very happy to lend my experience and insights to >> this process. I realize I may end up bringing things up that you all have >> discussed before - but considering that you did have a single Locale object >> at one point, I'd like to claim "great minds" think alike and continue >> discussing it. :) >> >> Happy Thanksgiving. >> >> -Nicholas >> >> >> >> On 11/24/2011 2:44 PM, Norbert Lindenberg wrote: >> >>> I didn't agree with this approach, and Nicholas didn't claim that I did >>> :-) >>> >>> I'm very glad though that Nicholas is taking the time to provide >>> feedback, come up with his own ideas, and discuss them with us. In the end, >>> the Globalization API can only be successful if people like him are >>> comfortable using the API in their projects, and explain it to others so >>> that they're comfortable doing so. Right now, the feedback from him, Rick, >>> several TC39 members, and others indicates significant discomfort, so we >>> have some work to do. Some of that work may be changes to the API, but some >>> may also be better explanation of how to use the API, directly from >>> applications or in higher-level libraries. >>> >>> More after Thanksgiving. >>> >>> Norbert >>> >>> >>> On Nov 23, 2011, at 15:15 , Nebojša Ćirić wrote: >>> >>> >>>> 23. новембар 2011. 14.32, Nicholas C. Zakas<[email protected]> >>>> је написао/ла: >>>> On 11/23/2011 12:57 PM, Nebojša Ćirić wrote: >>>> >>>>> 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) >>>>> >>>>> Sorry for being unclear - I didn't intend for this to be a complete >>>> alternate proposal, just a starting point. There are definitely still >>>> issues that would have to be resolved. >>>> >>>> I just feel we are going in circles sometimes :). I am surprised >>>> Norbert agreed with this approach - I think he was against top level Locale >>>> object. >>>> >>>> 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. >>>>> >>>> So what you're saying is that there needs to be some way to feature >>>> detect support for number and date formats separately. That could be >>>> handled in any number of ways. One that pops to mind would be >>>> isDateFormatSupported()/isNumberFormatSupported() as an instance method. >>>> >>>> That would probably work. We could add more methods in the future - say >>>> one that tells you closest locale to the current one that does support >>>> service in question. >>>> >>>> 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. >>>>> >>>> Thanks, I was having trouble understanding what resolvedOptions was >>>> used for. Could the use case be handled by having a similar object on a >>>> Locale instance? It seems like you could include options for available >>>> calendars and anything else that developers could query against, such as: >>>> >>>> >>>> var locale = new Locale(); >>>> if (locale.supportedOptions.islamicCalendar){ >>>> //foo >>>> } >>>> >>>> You could also go a more traditional direction (at least in terms of >>>> DOM objects), by doing something like: >>>> >>>> Locale.CALENDAR_ISLAMIC = 1; >>>> Locale.CALENDAR_GREGORIAN = 2; >>>> >>>> >>>> var locale = new Locale(); >>>> locale.isSupported(Locale.CALENDAR_ISLAMIC); >>>> >>>> I think feature detection is an easily solved problem if everything >>>> else is in place. >>>> >>>> Sometimes options can influence each other. For example: >>>> >>>> 1. Ask for th locale (Thai) >>>> 2. There are two calendars available - buddhist and gregory >>>> 3. There are two numbering systems available - thai and latin >>>> >>>> but only buddhist + thai and gregory + latin combinations are supported. >>>> >>>> If you ask locale.isSupported('calendar': 'buddhist') you'll get true. >>>> If you ask locale.isSupported('numberingSystem', 'latin') you'll get true >>>> again. If you try to format date using that combination (thai + latin) >>>> you'll get something you didn't expect. >>>> >>>> I would propose sligthly different isSupported method: >>>> >>>> locale.returnSupported(serviceName, options), where serviceName is one >>>> of 'dateFormat', 'numberFormat', 'collator', options object contains >>>> requested settings (calendar, numbering system, collation options...) and >>>> method returns the object with supported features for a given service. >>>> >>>>> 3. This approach would require internal caching of >>>>> collator/dateformatter/numberformatter objects. >>>>> >>>> That's an implementation detail. I'm more interested in defining an >>>> usable and relatively intuitive API before worrying about optimization. >>>> >>>> I agree, it's implementation detail, but you will need to pass format >>>> parameter to each call of .format() method. I don't think that's a big >>>> problem. Also I would move format and option parameters to the last >>>> position (can be optional), so that user can specify only value and rely on >>>> defaults. >>>> >>>>> 23. новембар 2011. 12.09, Nicholas C. Zakas< >>>>> [email protected]> је написао/ла: >>>>> 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 >>>>> >>>>> >>>>> >>>>> -- >>>>> Nebojša Ćirić >>>>> >>>> >>>> >>>> >>>> -- >>>> Nebojša Ćirić >>>> _______________________________________________ >>>> es-discuss mailing list >>>> [email protected] >>>> https://mail.mozilla.org/listinfo/es-discuss >>>> >>> >> >> > > > -- > Nebojša Ćirić > > > -- Nebojša Ćirić
_______________________________________________ es-discuss mailing list [email protected] https://mail.mozilla.org/listinfo/es-discuss

