Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(915)

Side by Side Diff: src/js/i18n.js

Issue 2248563003: Support language tag extensions with multiple subtags for a key (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: add a real test for nu in presence of multiple type subtags for ca Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/i18n.cc ('k') | test/intl/date-format/calendar-with-multiple-type-subtags.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // ECMAScript 402 API implementation. 5 // ECMAScript 402 API implementation.
6 6
7 /** 7 /**
8 * Intl object is a single object that has some named properties, 8 * Intl object is a single object that has some named properties,
9 * all of which are constructors. 9 * all of which are constructors.
10 */ 10 */
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after
377 } 377 }
378 378
379 return defaultValue; 379 return defaultValue;
380 } 380 }
381 381
382 return getOption; 382 return getOption;
383 } 383 }
384 384
385 385
386 /** 386 /**
387 * Ecma 402 9.2.5
388 * TODO(jshin): relevantExtensionKeys and localeData need to be taken into
389 * account per spec.
387 * Compares a BCP 47 language priority list requestedLocales against the locales 390 * Compares a BCP 47 language priority list requestedLocales against the locales
388 * in availableLocales and determines the best available language to meet the 391 * in availableLocales and determines the best available language to meet the
389 * request. Two algorithms are available to match the locales: the Lookup 392 * request. Two algorithms are available to match the locales: the Lookup
390 * algorithm described in RFC 4647 section 3.4, and an implementation dependent 393 * algorithm described in RFC 4647 section 3.4, and an implementation dependent
391 * best-fit algorithm. Independent of the locale matching algorithm, options 394 * best-fit algorithm. Independent of the locale matching algorithm, options
392 * specified through Unicode locale extension sequences are negotiated 395 * specified through Unicode locale extension sequences are negotiated
393 * separately, taking the caller's relevant extension keys and locale data as 396 * separately, taking the caller's relevant extension keys and locale data as
394 * well as client-provided options into consideration. Returns an object with 397 * well as client-provided options into consideration. Returns an object with
395 * a locale property whose value is the language tag of the selected locale, 398 * a locale property whose value is the language tag of the selected locale,
396 * and properties for each key in relevantExtensionKeys providing the selected 399 * and properties for each key in relevantExtensionKeys providing the selected
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
460 function bestFitMatcher(service, requestedLocales) { 463 function bestFitMatcher(service, requestedLocales) {
461 // TODO(cira): implement better best fit algorithm. 464 // TODO(cira): implement better best fit algorithm.
462 return lookupMatcher(service, requestedLocales); 465 return lookupMatcher(service, requestedLocales);
463 } 466 }
464 467
465 468
466 /** 469 /**
467 * Parses Unicode extension into key - value map. 470 * Parses Unicode extension into key - value map.
468 * Returns empty object if the extension string is invalid. 471 * Returns empty object if the extension string is invalid.
469 * We are not concerned with the validity of the values at this point. 472 * We are not concerned with the validity of the values at this point.
473 * 'attribute' in RFC 6047 is not supported. Keys without explicit
474 * values are assigned UNDEFINED.
475 * TODO(jshin): Fix the handling of 'attribute' (in RFC 6047, but none
476 * has been defined so that it's not used) and boolean keys without
477 * an explicit value.
470 */ 478 */
471 function parseExtension(extension) { 479 function parseExtension(extension) {
472 var extensionSplit = %StringSplit(extension, '-', kMaxUint32); 480 var extensionSplit = %StringSplit(extension, '-', kMaxUint32);
473 481
474 // Assume ['', 'u', ...] input, but don't throw. 482 // Assume ['', 'u', ...] input, but don't throw.
475 if (extensionSplit.length <= 2 || 483 if (extensionSplit.length <= 2 ||
476 (extensionSplit[0] !== '' && extensionSplit[1] !== 'u')) { 484 (extensionSplit[0] !== '' && extensionSplit[1] !== 'u')) {
477 return {}; 485 return {};
478 } 486 }
479 487
480 // Key is {2}alphanum, value is {3,8}alphanum. 488 // Key is {2}alphanum, value is {3,8}alphanum.
481 // Some keys may not have explicit values (booleans). 489 // Some keys may not have explicit values (booleans).
482 var extensionMap = {}; 490 var extensionMap = {};
483 var previousKey = UNDEFINED; 491 var key = UNDEFINED;
492 var value = UNDEFINED;
484 for (var i = 2; i < extensionSplit.length; ++i) { 493 for (var i = 2; i < extensionSplit.length; ++i) {
485 var length = extensionSplit[i].length; 494 var length = extensionSplit[i].length;
486 var element = extensionSplit[i]; 495 var element = extensionSplit[i];
487 if (length === 2) { 496 if (length === 2) {
488 extensionMap[element] = UNDEFINED; 497 if (!IS_UNDEFINED(key)) {
489 previousKey = element; 498 if (!(key in extensionMap)) {
490 } else if (length >= 3 && length <=8 && !IS_UNDEFINED(previousKey)) { 499 extensionMap[key] = value;
491 extensionMap[previousKey] = element; 500 }
492 previousKey = UNDEFINED; 501 value = UNDEFINED;
502 }
503 key = element;
504 } else if (length >= 3 && length <= 8 && !IS_UNDEFINED(key)) {
505 if (IS_UNDEFINED(value)) {
506 value = element;
507 } else {
508 value = value + "-" + element;
509 }
493 } else { 510 } else {
494 // There is a value that's too long, or that doesn't have a key. 511 // There is a value that's too long, or that doesn't have a key.
495 return {}; 512 return {};
496 } 513 }
497 } 514 }
515 if (!IS_UNDEFINED(key) && !(key in extensionMap)) {
516 extensionMap[key] = value;
517 }
498 518
499 return extensionMap; 519 return extensionMap;
500 } 520 }
501 521
502 522
503 /** 523 /**
504 * Populates internalOptions object with boolean key-value pairs 524 * Populates internalOptions object with boolean key-value pairs
505 * from extensionMap and options. 525 * from extensionMap and options.
506 * Returns filtered extension (number and date format constructors use 526 * Returns filtered extension (number and date format constructors use
507 * Unicode extensions for passing parameters to ICU). 527 * Unicode extensions for passing parameters to ICU).
(...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after
910 if (IS_UNDEFINED(sensitivity) && internalOptions.usage === 'sort') { 930 if (IS_UNDEFINED(sensitivity) && internalOptions.usage === 'sort') {
911 sensitivity = 'variant'; 931 sensitivity = 'variant';
912 } 932 }
913 defineWEProperty(internalOptions, 'sensitivity', sensitivity); 933 defineWEProperty(internalOptions, 'sensitivity', sensitivity);
914 934
915 defineWEProperty(internalOptions, 'ignorePunctuation', getOption( 935 defineWEProperty(internalOptions, 'ignorePunctuation', getOption(
916 'ignorePunctuation', 'boolean', UNDEFINED, false)); 936 'ignorePunctuation', 'boolean', UNDEFINED, false));
917 937
918 var locale = resolveLocale('collator', locales, options); 938 var locale = resolveLocale('collator', locales, options);
919 939
940 // TODO(jshin): ICU now can take kb, kc, etc. Switch over to using ICU
941 // directly. See Collator::InitializeCollator and
942 // Collator::CreateICUCollator in src/i18n.cc
920 // ICU can't take kb, kc... parameters through localeID, so we need to pass 943 // ICU can't take kb, kc... parameters through localeID, so we need to pass
921 // them as options. 944 // them as options.
922 // One exception is -co- which has to be part of the extension, but only for 945 // One exception is -co- which has to be part of the extension, but only for
923 // usage: sort, and its value can't be 'standard' or 'search'. 946 // usage: sort, and its value can't be 'standard' or 'search'.
924 var extensionMap = parseExtension(locale.extension); 947 var extensionMap = parseExtension(locale.extension);
925 948
926 /** 949 /**
927 * Map of Unicode extensions to option properties, and their values and types, 950 * Map of Unicode extensions to option properties, and their values and types,
928 * for a collator. 951 * for a collator.
929 */ 952 */
(...skipping 727 matching lines...) Expand 10 before | Expand all | Expand 10 after
1657 InstallFunction(Intl.DateTimeFormat.prototype, 'resolvedOptions', function() { 1680 InstallFunction(Intl.DateTimeFormat.prototype, 'resolvedOptions', function() {
1658 if (!IS_UNDEFINED(new.target)) { 1681 if (!IS_UNDEFINED(new.target)) {
1659 throw %make_type_error(kOrdinaryFunctionCalledAsConstructor); 1682 throw %make_type_error(kOrdinaryFunctionCalledAsConstructor);
1660 } 1683 }
1661 1684
1662 if (!%IsInitializedIntlObjectOfType(this, 'dateformat')) { 1685 if (!%IsInitializedIntlObjectOfType(this, 'dateformat')) {
1663 throw %make_type_error(kResolvedOptionsCalledOnNonObject, "DateTimeFormat" ); 1686 throw %make_type_error(kResolvedOptionsCalledOnNonObject, "DateTimeFormat" );
1664 } 1687 }
1665 1688
1666 /** 1689 /**
1667 * Maps ICU calendar names into LDML type. 1690 * Maps ICU calendar names to LDML/BCP47 types for key 'ca'.
1691 * See typeMap section in third_party/icu/source/data/misc/keyTypeData.txt
1692 * and
1693 * http://www.unicode.org/repos/cldr/tags/latest/common/bcp47/calendar.xml
1668 */ 1694 */
1669 var ICU_CALENDAR_MAP = { 1695 var ICU_CALENDAR_MAP = {
1670 'gregorian': 'gregory', 1696 'gregorian': 'gregory',
1671 'japanese': 'japanese',
1672 'buddhist': 'buddhist',
1673 'roc': 'roc',
1674 'persian': 'persian',
1675 'islamic-civil': 'islamicc',
1676 'islamic': 'islamic',
1677 'hebrew': 'hebrew',
1678 'chinese': 'chinese',
1679 'indian': 'indian',
1680 'coptic': 'coptic',
1681 'ethiopic': 'ethiopic',
1682 'ethiopic-amete-alem': 'ethioaa' 1697 'ethiopic-amete-alem': 'ethioaa'
1683 }; 1698 };
1684 1699
1685 var format = this; 1700 var format = this;
1686 var fromPattern = fromLDMLString(format[resolvedSymbol][patternSymbol]); 1701 var fromPattern = fromLDMLString(format[resolvedSymbol][patternSymbol]);
1687 var userCalendar = ICU_CALENDAR_MAP[format[resolvedSymbol].calendar]; 1702 var userCalendar = ICU_CALENDAR_MAP[format[resolvedSymbol].calendar];
1688 if (IS_UNDEFINED(userCalendar)) { 1703 if (IS_UNDEFINED(userCalendar)) {
1689 // Use ICU name if we don't have a match. It shouldn't happen, but 1704 // No match means that ICU's legacy name is identical to LDML/BCP type.
1690 // it would be too strict to throw for this.
1691 userCalendar = format[resolvedSymbol].calendar; 1705 userCalendar = format[resolvedSymbol].calendar;
1692 } 1706 }
1693 1707
1694 var locale = getOptimalLanguageTag(format[resolvedSymbol].requestedLocale, 1708 var locale = getOptimalLanguageTag(format[resolvedSymbol].requestedLocale,
1695 format[resolvedSymbol].locale); 1709 format[resolvedSymbol].locale);
1696 1710
1697 var result = { 1711 var result = {
1698 locale: locale, 1712 locale: locale,
1699 numberingSystem: format[resolvedSymbol].numberingSystem, 1713 numberingSystem: format[resolvedSymbol].numberingSystem,
1700 calendar: userCalendar, 1714 calendar: userCalendar,
(...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after
2246 } 2260 }
2247 ); 2261 );
2248 2262
2249 utils.Export(function(to) { 2263 utils.Export(function(to) {
2250 to.AddBoundMethod = AddBoundMethod; 2264 to.AddBoundMethod = AddBoundMethod;
2251 to.IntlParseDate = IntlParseDate; 2265 to.IntlParseDate = IntlParseDate;
2252 to.IntlParseNumber = IntlParseNumber; 2266 to.IntlParseNumber = IntlParseNumber;
2253 }); 2267 });
2254 2268
2255 }) 2269 })
OLDNEW
« no previous file with comments | « src/i18n.cc ('k') | test/intl/date-format/calendar-with-multiple-type-subtags.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698