6#error Internationalization is expected to be enabled.
22#include "unicode/dtfmtsym.h"
23#include "unicode/dtptngen.h"
24#include "unicode/localebuilder.h"
25#include "unicode/locdspnm.h"
26#include "unicode/measfmt.h"
27#include "unicode/timezone.h"
28#include "unicode/tznames.h"
29#include "unicode/uloc.h"
30#include "unicode/unistr.h"
31#include "unicode/uscript.h"
50bool IsUnicodeScriptSubtag(
const std::string& value) {
51 UErrorCode status = U_ZERO_ERROR;
52 icu::LocaleBuilder builder;
53 builder.setScript(value).build(status);
54 return U_SUCCESS(status);
57bool IsUnicodeRegionSubtag(
const std::string& value) {
58 if (value.empty())
return false;
59 UErrorCode status = U_ZERO_ERROR;
60 icu::LocaleBuilder builder;
61 builder.setRegion(value).build(status);
62 return U_SUCCESS(status);
68 return UDISPCTX_LENGTH_FULL;
71 return UDISPCTX_LENGTH_SHORT;
84 virtual const char*
type()
const = 0;
85 virtual icu::Locale
locale()
const = 0;
87 const char* code)
const = 0;
94 LocaleDisplayNamesCommon(
const icu::Locale& locale,
99 fallback ? UDISPCTX_SUBSTITUTE : UDISPCTX_NO_SUBSTITUTE;
100 UDisplayContext dialect_context =
101 dialect ? UDISPCTX_DIALECT_NAMES : UDISPCTX_STANDARD_NAMES;
102 UDisplayContext display_context[] = {ToUDisplayContext(
style_),
104 UDISPCTX_CAPITALIZATION_NONE, sub};
106 icu::LocaleDisplayNames::createInstance(locale, display_context, 4));
109 ~LocaleDisplayNamesCommon()
override =
default;
111 icu::Locale locale()
const override {
return ldn_->getLocale(); }
114 icu::LocaleDisplayNames* locale_display_names()
const {
return ldn_.get(); }
117 std::unique_ptr<icu::LocaleDisplayNames>
ldn_;
121class LanguageNames :
public LocaleDisplayNamesCommon {
124 bool fallback,
bool dialect)
125 : LocaleDisplayNamesCommon(locale,
style, fallback, dialect) {}
127 ~LanguageNames()
override =
default;
129 const char*
type()
const override {
return "language"; }
131 Maybe<icu::UnicodeString> of(Isolate* isolate,
132 const char* code)
const override {
133 UErrorCode status = U_ZERO_ERROR;
136 icu::Locale tagLocale = icu::Locale::forLanguageTag(code, status);
137 icu::Locale
l(tagLocale.getBaseName());
138 if (U_FAILURE(status) || tagLocale != l ||
141 isolate, NewRangeError(MessageTemplate::kInvalidArgument),
149 l.canonicalize(status);
150 std::string checked = l.toLanguageTag<std::string>(
status);
152 if (U_FAILURE(status)) {
154 isolate, NewRangeError(MessageTemplate::kInvalidArgument),
158 icu::UnicodeString
result;
159 locale_display_names()->localeDisplayName(checked.c_str(),
result);
165class RegionNames :
public LocaleDisplayNamesCommon {
168 bool fallback,
bool dialect)
169 : LocaleDisplayNamesCommon(locale,
style, fallback, dialect) {}
171 ~RegionNames()
override =
default;
173 const char*
type()
const override {
return "region"; }
175 Maybe<icu::UnicodeString> of(Isolate* isolate,
176 const char* code)
const override {
177 std::string code_str(code);
178 if (!IsUnicodeRegionSubtag(code_str)) {
180 isolate, NewRangeError(MessageTemplate::kInvalidArgument),
184 icu::UnicodeString
result;
185 locale_display_names()->regionDisplayName(code_str.c_str(),
result);
190class ScriptNames :
public LocaleDisplayNamesCommon {
193 bool fallback,
bool dialect)
194 : LocaleDisplayNamesCommon(locale,
style, fallback, dialect) {}
196 ~ScriptNames()
override =
default;
198 const char*
type()
const override {
return "script"; }
200 Maybe<icu::UnicodeString> of(Isolate* isolate,
201 const char* code)
const override {
202 std::string code_str(code);
203 if (!IsUnicodeScriptSubtag(code_str)) {
205 isolate, NewRangeError(MessageTemplate::kInvalidArgument),
209 icu::UnicodeString
result;
210 locale_display_names()->scriptDisplayName(code_str.c_str(),
result);
215class KeyValueDisplayNames :
public LocaleDisplayNamesCommon {
218 bool fallback,
bool dialect,
const char*
key,
219 bool prevent_fallback)
220 : LocaleDisplayNamesCommon(locale,
style, fallback, dialect),
224 ~KeyValueDisplayNames()
override =
default;
226 const char*
type()
const override {
return key_.c_str(); }
228 Maybe<icu::UnicodeString> of(Isolate* isolate,
229 const char* code)
const override {
230 std::string code_str(code);
231 icu::UnicodeString
result;
232 locale_display_names()->keyValueDisplayName(
key_.c_str(), code_str.c_str(),
236 if (prevent_fallback_ && (
result.length() == 3) &&
237 (code_str.length() == 3) &&
238 (
result == icu::UnicodeString(code_str.c_str(), -1, US_INV))) {
250class CurrencyNames :
public KeyValueDisplayNames {
253 bool fallback,
bool dialect)
254 : KeyValueDisplayNames(locale,
style, fallback, dialect,
"currency",
255 fallback ==
false) {}
257 ~CurrencyNames()
override =
default;
259 Maybe<icu::UnicodeString> of(Isolate* isolate,
260 const char* code)
const override {
261 std::string code_str(code);
264 isolate, NewRangeError(MessageTemplate::kInvalidArgument),
267 return KeyValueDisplayNames::of(isolate, code);
271class CalendarNames :
public KeyValueDisplayNames {
274 bool fallback,
bool dialect)
275 : KeyValueDisplayNames(locale,
style, fallback, dialect,
"calendar",
278 ~CalendarNames()
override =
default;
280 Maybe<icu::UnicodeString> of(Isolate* isolate,
281 const char* code)
const override {
282 std::string code_str(code);
285 isolate, NewRangeError(MessageTemplate::kInvalidArgument),
288 return KeyValueDisplayNames::of(isolate, strcmp(code,
"gregory") == 0
290 : strcmp(code,
"ethioaa") == 0
291 ?
"ethiopic-amete-alem"
296UDateTimePGDisplayWidth StyleToUDateTimePGDisplayWidth(
302 return UDATPG_ABBREVIATED;
304 return UDATPG_NARROW;
308UDateTimePatternField StringToUDateTimePatternField(
const char* code) {
311 if (strcmp(code,
"day") == 0)
return UDATPG_DAY_FIELD;
312 if (strcmp(code,
"dayPeriod") == 0)
return UDATPG_DAYPERIOD_FIELD;
315 if (strcmp(code,
"era") == 0)
return UDATPG_ERA_FIELD;
318 if (strcmp(code,
"hour") == 0)
return UDATPG_HOUR_FIELD;
321 if (strcmp(code,
"minute") == 0)
return UDATPG_MINUTE_FIELD;
322 if (strcmp(code,
"month") == 0)
return UDATPG_MONTH_FIELD;
325 if (strcmp(code,
"quarter") == 0)
return UDATPG_QUARTER_FIELD;
328 if (strcmp(code,
"second") == 0)
return UDATPG_SECOND_FIELD;
331 if (strcmp(code,
"timeZoneName") == 0)
return UDATPG_ZONE_FIELD;
334 if (strcmp(code,
"weekOfYear") == 0)
return UDATPG_WEEK_OF_YEAR_FIELD;
335 if (strcmp(code,
"weekday") == 0)
return UDATPG_WEEKDAY_FIELD;
338 if (strcmp(code,
"year") == 0)
return UDATPG_YEAR_FIELD;
343 return UDATPG_FIELD_COUNT;
346class DateTimeFieldNames :
public DisplayNamesInternal {
351 UErrorCode status = U_ZERO_ERROR;
353 icu::DateTimePatternGenerator::createInstance(locale_, status));
354 DCHECK(U_SUCCESS(status));
357 ~DateTimeFieldNames()
override =
default;
359 const char*
type()
const override {
return "dateTimeField"; }
361 icu::Locale locale()
const override {
return locale_; }
363 Maybe<icu::UnicodeString> of(Isolate* isolate,
364 const char* code)
const override {
365 UDateTimePatternField field = StringToUDateTimePatternField(code);
366 if (field == UDATPG_FIELD_COUNT) {
368 isolate, NewRangeError(MessageTemplate::kInvalidArgument),
380DisplayNamesInternal* CreateInternal(
const icu::Locale& locale,
382 bool fallback,
bool dialect) {
384 case Type::kLanguage:
385 return new LanguageNames(locale,
style, fallback, dialect);
387 return new RegionNames(locale,
style, fallback,
false);
389 return new ScriptNames(locale,
style, fallback,
false);
390 case Type::kCurrency:
391 return new CurrencyNames(locale,
style, fallback,
false);
392 case Type::kCalendar:
393 return new CalendarNames(locale,
style, fallback,
false);
394 case Type::kDateTimeField:
395 return new DateTimeFieldNames(locale,
style, fallback);
407 const char* service =
"Intl.DisplayNames";
408 Factory* factory = isolate->factory();
415 std::vector<std::string> requested_locales =
439 std::set<std::string> relevant_extension_keys = {};
444 requested_locales, matcher, relevant_extension_keys);
450 icu::Locale icu_locale =
r.icu_locale;
455 isolate, options,
"style", service, {
"long",
"short",
"narrow"},
466 isolate, options,
"type", service,
467 {
"language",
"region",
"script",
"currency",
"calendar",
"dateTimeField"},
468 {Type::kLanguage, Type::kRegion, Type::kScript, Type::kCurrency,
469 Type::kCalendar, Type::kDateTimeField},
475 if (type_enum == Type::kUndefined) {
476 THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kInvalidArgument));
484 isolate, options,
"fallback", service, {
"code",
"none"},
496 isolate, options,
"languageDisplay", service, {
"dialect",
"standard"},
501 if (type_enum == Type::kLanguage) {
503 language_display_enum = maybe_language_display.
FromJust();
528 std::shared_ptr<DisplayNamesInternal>
internal{CreateInternal(
540 display_names->set_flags(0);
541 display_names->set_style(style_enum);
542 display_names->set_fallback(fallback_enum);
543 display_names->set_language_display(language_display_enum);
546 display_names->set_internal(*managed_internal);
549 return display_names;
555 Factory* factory = isolate->factory();
571 display_names->LanguageDisplayAsString(isolate);
574 isolate, options, factory->locale_string(), locale,
Just(
kDontThrow));
576 USE(maybe_create_locale);
581 USE(maybe_create_style);
584 isolate, options, factory->type_string(), type,
Just(
kDontThrow));
586 USE(maybe_create_type);
591 USE(maybe_create_fallback);
593 if (std::strcmp(
"language",
internal->type()) == 0) {
596 factory->languageDisplay_string(),
599 USE(maybe_create_language_display);
614 internal->of(isolate, code->ToCString().get());
618 return isolate->factory()->undefined_value();
625struct CheckCalendar {
626 static const char*
key() {
return "calendar"; }
627 static const char* path() {
return nullptr; }
635 return available_locales.Pointer()->Get();
641 return isolate->factory()->long_string();
643 return isolate->factory()->short_string();
645 return isolate->factory()->narrow_string();
653 return isolate->factory()->code_string();
655 return isolate->factory()->none_string();
664 return isolate->factory()->dialect_string();
666 return isolate->factory()->standard_string();
V8_INLINE bool IsJust() const
V8_INLINE T FromJust() const &
V8_INLINE bool IsNothing() const
virtual const char * type() const =0
virtual Maybe< icu::UnicodeString > of(Isolate *isolate, const char *code) const =0
static constexpr ExternalPointerTag kManagedTag
DisplayNamesInternal()=default
virtual icu::Locale locale() const =0
virtual ~DisplayNamesInternal()=default
Handle< String > NewStringFromAsciiChecked(const char *str, AllocationType allocation=AllocationType::kYoung)
Handle< JSObject > NewJSObject(DirectHandle< JSFunction > constructor, AllocationType allocation=AllocationType::kYoung, NewJSObjectType=NewJSObjectType::kNoAPIWrapper)
Handle< JSObject > NewFastOrSlowJSObjectFromMap(DirectHandle< Map > map, int number_of_slow_properties, AllocationType allocation=AllocationType::kYoung, DirectHandle< AllocationSite > allocation_site=DirectHandle< AllocationSite >::null(), NewJSObjectType=NewJSObjectType::kNoAPIWrapper)
static bool IsWellFormedCurrency(const std::string &value)
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 bool IsWellFormedCalendar(const std::string &value)
static Maybe< std::string > ToLanguageTag(const icu::Locale &locale)
static MaybeDirectHandle< Object > Of(Isolate *isolate, DirectHandle< JSDisplayNames > holder, Handle< Object > code_obj)
static V8_EXPORT_PRIVATE const std::set< std::string > & GetAvailableLocales()
LanguageDisplay language_display() const
Handle< String > StyleAsString(Isolate *isolate) const
DirectHandle< String > LanguageDisplayAsString(Isolate *isolate) const
Handle< String > FallbackAsString(Isolate *isolate) const
static MaybeDirectHandle< JSDisplayNames > New(Isolate *isolate, DirectHandle< Map > map, DirectHandle< Object > locales, DirectHandle< Object > options)
static DirectHandle< JSObject > ResolvedOptions(Isolate *isolate, DirectHandle< JSDisplayNames > format_holder)
Fallback fallback() const
static bool StartsWithUnicodeLanguageId(const std::string &value)
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 V8_WARN_UNUSED_RESULT HandleType< String >::MaybeType ToString(Isolate *isolate, HandleType< T > input)
Handle< SharedFunctionInfo > key_
#define THROW_NEW_ERROR_RETURN_VALUE(isolate, call, value)
#define ASSIGN_RETURN_ON_EXCEPTION(isolate, dst, call)
#define THROW_NEW_ERROR(isolate, call)
#define MAYBE_RETURN(call, value)
JSDisplayNames::Style style_
std::unique_ptr< icu::DateTimePatternGenerator > generator_
UDateTimePGDisplayWidth width_
std::unique_ptr< icu::LocaleDisplayNames > ldn_
DirectHandle< JSReceiver > options
ZoneVector< RpoNumber > & result
#define LAZY_INSTANCE_INITIALIZER
MaybeDirectHandle< JSReceiver > GetOptionsObject(Isolate *isolate, DirectHandle< Object > options, const char *method_name)
@ kDisplayNamesInternalTag
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(condition)