6#error Internationalization is expected to be enabled.
17#pragma GCC diagnostic push
18#pragma GCC diagnostic ignored "-Wshadow"
19#include "unicode/locid.h"
20#include "unicode/numberformatter.h"
21#include "unicode/numberrangeformatter.h"
22#include "unicode/plurrule.h"
23#include "unicode/unumberformatter.h"
24#pragma GCC diagnostic pop
31bool CreateICUPluralRules(Isolate* isolate,
const icu::Locale& icu_locale,
33 std::unique_ptr<icu::PluralRules>*
pl) {
36 UErrorCode status = U_ZERO_ERROR;
38 UPluralType icu_type = UPLURAL_TYPE_CARDINAL;
40 icu_type = UPLURAL_TYPE_ORDINAL;
45 std::unique_ptr<icu::PluralRules> plural_rules(
46 icu::PluralRules::forLocale(icu_locale, icu_type, status));
47 if (U_FAILURE(status)) {
52 *
pl = std::move(plural_rules);
61 return isolate->factory()->cardinal_string();
63 return isolate->factory()->ordinal_string();
76 std::vector<std::string> requested_locales =
81 const char* service =
"Intl.PluralRules";
96 isolate, options,
"type", service, {
"cardinal",
"ordinal"},
112 requested_locales, matcher, {});
118 isolate->factory()->NewStringFromAsciiChecked(
r.locale.c_str());
120 icu::Locale icu_locale =
r.icu_locale;
121 icu::number::UnlocalizedNumberFormatter settings =
122 icu::number::UnlocalizedNumberFormatter().roundingMode(UNUM_ROUND_HALFUP);
124 std::unique_ptr<icu::PluralRules> icu_plural_rules;
126 CreateICUPluralRules(isolate,
r.icu_locale, type, &icu_plural_rules);
127 if (!success || icu_plural_rules ==
nullptr) {
129 icu::Locale no_extension_locale(icu_locale.getBaseName());
130 success = CreateICUPluralRules(isolate, no_extension_locale, type,
132 icu_locale = no_extension_locale;
134 if (!success || icu_plural_rules ==
nullptr) {
148 settings.locale(icu_locale);
154 managed_number_formatter =
157 std::make_shared<icu::number::LocalizedNumberFormatter>(
162 isolate->factory()->NewFastOrSlowJSObjectFromMap(map));
164 plural_rules->set_flags(0);
167 plural_rules->set_type(type);
170 plural_rules->set_locale(*locale_str);
172 plural_rules->set_icu_plural_rules(*managed_plural_rules);
173 plural_rules->set_icu_number_formatter(*managed_number_formatter);
181 icu::PluralRules* icu_plural_rules = plural_rules->icu_plural_rules()->raw();
184 icu::number::LocalizedNumberFormatter* fmt =
185 plural_rules->icu_number_formatter()->raw();
188 UErrorCode status = U_ZERO_ERROR;
189 icu::number::FormattedNumber formatted_number =
190 fmt->formatDouble(number, status);
191 DCHECK(U_SUCCESS(status));
193 icu::UnicodeString
result =
194 icu_plural_rules->select(formatted_number, status);
195 DCHECK(U_SUCCESS(status));
203 icu::PluralRules* icu_plural_rules = plural_rules->icu_plural_rules()->raw();
208 isolate, plural_rules->locale(),
209 *plural_rules->icu_number_formatter()->raw());
212 icu::number::LocalizedNumberRangeFormatter nrfmt =
215 UErrorCode status = U_ZERO_ERROR;
216 icu::number::FormattedNumberRange
formatted = nrfmt.formatFormattableRange(
217 icu::Formattable(
x), icu::Formattable(
y), status);
219 DCHECK(U_SUCCESS(status));
220 icu::UnicodeString
result = icu_plural_rules->select(
formatted, status);
221 DCHECK(U_SUCCESS(status));
228void CreateDataPropertyForOptions(
Isolate* isolate,
232 isolate->factory()->NewStringFromAsciiChecked(
key);
242void CreateDataPropertyForOptions(
Isolate* isolate,
243 DirectHandle<JSObject> options,
int value,
245 DirectHandle<Smi> value_smi(
Smi::FromInt(value), isolate);
246 CreateDataPropertyForOptions(isolate, options, value_smi,
key);
254 isolate->factory()->NewJSObject(isolate->object_function());
257 CreateDataPropertyForOptions(isolate, options, locale_value,
"locale");
259 CreateDataPropertyForOptions(isolate, options,
260 plural_rules->TypeAsString(isolate),
"type");
262 UErrorCode status = U_ZERO_ERROR;
264 plural_rules->icu_number_formatter()->raw();
266 DCHECK(U_SUCCESS(status));
268 CreateDataPropertyForOptions(
271 "minimumIntegerDigits");
272 int32_t min = 0, max = 0;
275 CreateDataPropertyForOptions(isolate, options, min,
276 "minimumSignificantDigits");
277 CreateDataPropertyForOptions(isolate, options, max,
278 "maximumSignificantDigits");
281 CreateDataPropertyForOptions(isolate, options, min,
282 "minimumFractionDigits");
283 CreateDataPropertyForOptions(isolate, options, max,
284 "maximumFractionDigits");
291 icu::PluralRules* icu_plural_rules = plural_rules->icu_plural_rules()->raw();
294 std::unique_ptr<icu::StringEnumeration> categories(
295 icu_plural_rules->getKeywords(status));
296 DCHECK(U_SUCCESS(status));
297 int32_t
count = categories->count(status);
298 DCHECK(U_SUCCESS(status));
300 Factory* factory = isolate->factory();
302 const std::vector<const char*> kCategories = {
"zero",
"one",
"two",
303 "few",
"many",
"other"};
305 std::for_each(kCategories.cbegin(), kCategories.cend(), [&](
const char* val) {
306 categories->reset(status);
307 DCHECK(U_SUCCESS(status));
308 for (int32_t i = 0; i < count; i++) {
310 const char* cat = categories->next(&len, status);
311 DCHECK(U_SUCCESS(status));
312 if (cat == nullptr) break;
313 if (std::strcmp(val, cat) == 0) {
314 DirectHandle<String> value_string =
315 factory->NewStringFromAsciiChecked(val);
316 plural_categories->set(index++, *value_string);
326 factory->NewJSArrayWithElements(plural_categories);
327 CreateDataPropertyForOptions(isolate, options, plural_categories_value,
331 isolate, options, factory->roundingIncrement_string(),
336 isolate, options, factory->roundingMode_string(),
341 isolate, options, factory->roundingPriority_string(),
346 isolate, options, factory->trailingZeroDisplay_string(),
356class PluralRulesAvailableLocales {
358 PluralRulesAvailableLocales() {
359 UErrorCode status = U_ZERO_ERROR;
360 std::unique_ptr<icu::StringEnumeration> locales(
361 icu::PluralRules::getAvailableLocales(status));
362 DCHECK(U_SUCCESS(status));
364 const char* locale =
nullptr;
365 while ((locale = locales->next(&len, status)) !=
nullptr &&
367 std::string str(locale);
369 std::replace(str.begin(), str.end(),
'_',
'-');
371 set_.insert(std::move(str));
374 const std::set<std::string>&
Get()
const {
return set_; }
382const std::set<std::string>& JSPluralRules::GetAvailableLocales() {
385 return available_locales.Pointer()->Get();
V8_INLINE T FromJust() const &
V8_INLINE bool IsNothing() const
Handle< FixedArray > NewFixedArray(int length, AllocationType allocation=AllocationType::kYoung)
static V8_WARN_UNUSED_RESULT MaybeHandle< String > ToString(Isolate *isolate, const icu::UnicodeString &string)
static Maybe< std::vector< std::string > > CanonicalizeLocaleList(Isolate *isolate, DirectHandle< Object > locales, bool only_return_one_result=false)
static Maybe< ResolvedLocale > ResolveLocale(Isolate *isolate, const std::set< std::string > &available_locales, const std::vector< std::string > &requested_locales, MatcherOption options, const std::set< std::string > &relevant_extension_keys)
static V8_WARN_UNUSED_RESULT Maybe< MatcherOption > GetLocaleMatcher(Isolate *isolate, DirectHandle< JSReceiver > options, const char *method_name)
static V8_WARN_UNUSED_RESULT Maybe< NumberFormatDigitOptions > SetNumberFormatDigitOptions(Isolate *isolate, DirectHandle< JSReceiver > options, int mnfd_default, int mxfd_default, bool notation_is_compact, const char *service)
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< String > ResolvePlural(Isolate *isolate, DirectHandle< JSPluralRules > plural_rules, double number)
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< String > ResolvePluralRange(Isolate *isolate, DirectHandle< JSPluralRules > plural_rules, double x, double y)
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< JSPluralRules > New(Isolate *isolate, DirectHandle< Map > map, DirectHandle< Object > locales, DirectHandle< Object > options)
Handle< String > TypeAsString(Isolate *isolate) const
static DirectHandle< JSObject > ResolvedOptions(Isolate *isolate, DirectHandle< JSPluralRules > plural_rules)
static V8_EXPORT_PRIVATE const std::set< std::string > & GetAvailableLocales()
static V8_WARN_UNUSED_RESULT Maybe< bool > CreateDataProperty(Isolate *isolate, DirectHandle< JSReceiver > object, DirectHandle< Name > key, DirectHandle< Object > value, Maybe< ShouldThrow > should_throw)
static DirectHandle< Managed< CppType > > From(Isolate *isolate, size_t estimated_size, std::shared_ptr< CppType > shared_ptr, AllocationType allocation_type=AllocationType::kYoung)
static constexpr Tagged< Smi > FromInt(int value)
#define ASSIGN_RETURN_ON_EXCEPTION(isolate, dst, call)
#define THROW_NEW_ERROR(isolate, call)
#define MAYBE_RETURN(call, value)
DirectHandle< JSReceiver > options
ZoneVector< RpoNumber > & result
#define LAZY_INSTANCE_INITIALIZER
ZoneVector< InstructionOperand > * set_
V8_INLINE const Operation & Get(const Graph &graph, OpIndex index)
MaybeDirectHandle< JSReceiver > CoerceOptionsToObject(Isolate *isolate, DirectHandle< Object > options, const char *method_name)
Maybe< bool > GetStringOption(Isolate *isolate, DirectHandle< JSReceiver > options, const char *property, const std::vector< const char * > &values, const char *method_name, std::unique_ptr< char[]> *result)
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Maybe< T > Just(const T &t)
#define DCHECK_NOT_NULL(val)
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)
typename LazyStaticInstance< T, CreateTrait, InitOnceTrait, DestroyTrait >::type type