Chromium Code Reviews| 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); |