Index: src/runtime/runtime-i18n.cc |
diff --git a/src/runtime/runtime-i18n.cc b/src/runtime/runtime-i18n.cc |
index df60891c2527ad9b8c83c0654ef1f3070ce33794..48597c5049a9d758da510c436c244d80956e44de 100644 |
--- a/src/runtime/runtime-i18n.cc |
+++ b/src/runtime/runtime-i18n.cc |
@@ -33,6 +33,7 @@ |
#include "unicode/normalizer2.h" |
#include "unicode/numfmt.h" |
#include "unicode/numsys.h" |
+#include "unicode/plurrule.h" |
#include "unicode/rbbi.h" |
#include "unicode/smpdtfmt.h" |
#include "unicode/timezone.h" |
@@ -123,6 +124,15 @@ RUNTIME_FUNCTION(Runtime_AvailableLocalesOf) { |
available_locales = icu::DateFormat::getAvailableLocales(count); |
} else if (service->IsUtf8EqualTo(CStrVector("breakiterator"))) { |
available_locales = icu::BreakIterator::getAvailableLocales(count); |
+ } else if (service->IsUtf8EqualTo(CStrVector("pluralrules"))) { |
+ // TODO(littledan): For PluralRules, filter out locales that |
+ // don't support PluralRules. |
+ // PluralRules is missing an appropriate getAvailableLocales method, |
+ // so we should filter from all locales, but it's not clear how; see |
+ // https://ssl.icu-project.org/trac/ticket/12756 |
+ available_locales = icu::Locale::getAvailableLocales(count); |
+ } else { |
+ UNREACHABLE(); |
} |
UErrorCode error = U_ZERO_ERROR; |
@@ -638,6 +648,81 @@ RUNTIME_FUNCTION(Runtime_InternalCompare) { |
return *isolate->factory()->NewNumberFromInt(result); |
} |
+RUNTIME_FUNCTION(Runtime_CreatePluralRules) { |
+ HandleScope scope(isolate); |
+ |
+ DCHECK_EQ(3, args.length()); |
+ |
+ CONVERT_ARG_HANDLE_CHECKED(String, locale, 0); |
+ CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1); |
+ CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2); |
+ |
+ Handle<JSFunction> constructor( |
+ isolate->native_context()->intl_plural_rules_function()); |
+ |
+ Handle<JSObject> local_object; |
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, local_object, |
+ JSObject::New(constructor, constructor)); |
+ |
+ // Set pluralRules as internal field of the resulting JS object. |
+ icu::PluralRules* plural_rules; |
+ icu::DecimalFormat* decimal_format; |
+ bool success = PluralRules::InitializePluralRules( |
+ isolate, locale, options, resolved, &plural_rules, &decimal_format); |
+ |
+ if (!success) return isolate->ThrowIllegalOperation(); |
+ |
+ local_object->SetInternalField(0, reinterpret_cast<Smi*>(plural_rules)); |
+ local_object->SetInternalField(1, reinterpret_cast<Smi*>(decimal_format)); |
+ |
+ Handle<Object> wrapper = isolate->global_handles()->Create(*local_object); |
+ GlobalHandles::MakeWeak(wrapper.location(), wrapper.location(), |
+ PluralRules::DeletePluralRules, |
+ WeakCallbackType::kInternalFields); |
+ return *local_object; |
+} |
+ |
+RUNTIME_FUNCTION(Runtime_PluralRulesSelect) { |
+ HandleScope scope(isolate); |
+ |
+ DCHECK_EQ(2, args.length()); |
+ |
+ CONVERT_ARG_HANDLE_CHECKED(JSObject, plural_rules_holder, 0); |
+ CONVERT_ARG_HANDLE_CHECKED(Object, number, 1); |
+ |
+ icu::PluralRules* plural_rules = |
+ PluralRules::UnpackPluralRules(isolate, plural_rules_holder); |
+ CHECK_NOT_NULL(plural_rules); |
+ |
+ icu::DecimalFormat* number_format = |
+ PluralRules::UnpackNumberFormat(isolate, plural_rules_holder); |
+ CHECK_NOT_NULL(number_format); |
+ |
+ // Currently, PluralRules doesn't implement all the options for rounding that |
+ // the Intl spec provides; format and parse the number to round to the |
+ // appropriate amount, then apply PluralRules. |
+ // |
+ // TODO(littledan): If a future ICU version supports an extended API to avoid |
+ // this step, then switch to that API. Bug thread: |
+ // http://bugs.icu-project.org/trac/ticket/12763 |
jungshik at Google
2017/05/08 19:16:54
Fixed in ICU 59.1. Either wait for me to update Ch
Dan Ehrenberg
2017/07/14 08:31:50
Looks like that API is C-only. I posted a comment
|
+ icu::UnicodeString rounded_string; |
+ number_format->format(number->Number(), rounded_string); |
+ |
+ icu::Formattable formattable; |
+ UErrorCode status = U_ZERO_ERROR; |
+ number_format->parse(rounded_string, formattable, status); |
+ if (!U_SUCCESS(status)) return isolate->ThrowIllegalOperation(); |
jungshik at Google
2017/05/08 19:16:54
again, check at line 717 would suffice. If you wan
|
+ |
+ double rounded = formattable.getDouble(status); |
+ if (!U_SUCCESS(status)) return isolate->ThrowIllegalOperation(); |
+ |
+ icu::UnicodeString result = plural_rules->select(rounded); |
+ return *isolate->factory() |
+ ->NewStringFromTwoByte(Vector<const uint16_t>( |
+ reinterpret_cast<const uint16_t*>(result.getBuffer()), |
+ result.length())) |
+ .ToHandleChecked(); |
+} |
RUNTIME_FUNCTION(Runtime_StringNormalize) { |
HandleScope scope(isolate); |