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

Unified Diff: src/runtime/runtime-i18n.cc

Issue 2736543002: [intl] Implement Intl.PluralRules
Patch Set: clarify comment Created 3 years, 9 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 side-by-side diff with in-line comments
Download patch
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);
« src/i18n.cc ('K') | « src/runtime/runtime.h ('k') | test/test262/test262.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698