ladybird/Userland/Libraries/LibJS/Runtime/Intl/Locale.cpp

148 lines
6.7 KiB
C++

/*
* Copyright (c) 2021-2022, Tim Flynn <trflynn89@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibJS/Runtime/Array.h>
#include <LibJS/Runtime/GlobalObject.h>
#include <LibJS/Runtime/Intl/Locale.h>
#include <LibUnicode/Locale.h>
namespace JS::Intl {
Locale* Locale::create(GlobalObject& global_object, Unicode::LocaleID const& locale_id)
{
return global_object.heap().allocate<Locale>(global_object, locale_id, *global_object.intl_locale_prototype());
}
// 14 Locale Objects, https://tc39.es/ecma402/#locale-objects
Locale::Locale(Object& prototype)
: Object(prototype)
{
}
Locale::Locale(Unicode::LocaleID const& locale_id, Object& prototype)
: Object(prototype)
{
set_locale(locale_id.to_string());
for (auto const& extension : locale_id.extensions) {
if (!extension.has<Unicode::LocaleExtension>())
continue;
for (auto const& keyword : extension.get<Unicode::LocaleExtension>().keywords) {
if (keyword.key == "ca"sv) {
set_calendar(keyword.value);
} else if (keyword.key == "co"sv) {
set_collation(keyword.value);
} else if (keyword.key == "hc"sv) {
set_hour_cycle(keyword.value);
} else if (keyword.key == "kf"sv) {
set_case_first(keyword.value);
} else if (keyword.key == "kn"sv) {
set_numeric(keyword.value.is_empty());
} else if (keyword.key == "nu"sv) {
set_numbering_system(keyword.value);
}
}
break;
}
}
// 1.1.1 CreateArrayFromListOrRestricted ( list , restricted )
static Array* create_array_from_list_or_restricted(GlobalObject& global_object, Vector<StringView> list, Optional<String> restricted)
{
auto& vm = global_object.vm();
// 1. If restricted is not undefined, then
if (restricted.has_value()) {
// a. Set list to « restricted ».
list = { *restricted };
}
// 2. Return ! CreateArrayFromList( list ).
return Array::create_from<StringView>(global_object, list, [&vm](auto value) {
return js_string(vm, value);
});
}
// 1.1.2 CalendarsOfLocale ( loc ), https://tc39.es/proposal-intl-locale-info/#sec-calendars-of-locale
Array* calendars_of_locale(GlobalObject& global_object, Locale const& locale_object)
{
// 1. Let restricted be loc.[[Calendar]].
Optional<String> restricted = locale_object.has_calendar() ? locale_object.calendar() : Optional<String> {};
// 2. Let locale be loc.[[Locale]].
auto const& locale = locale_object.locale();
// 3. Assert: locale matches the unicode_locale_id production.
VERIFY(Unicode::parse_unicode_locale_id(locale).has_value());
// 4. Let list be a List of 1 or more unique canonical calendar identifiers, which must be lower case String values conforming to the type sequence from UTS 35 Unicode Locale Identifier, section 3.2, sorted in descending preference of those in common use for date and time formatting in locale.
auto list = Unicode::get_keywords_for_locale(locale, "ca"sv);
// 5. Return ! CreateArrayFromListOrRestricted( list, restricted ).
return create_array_from_list_or_restricted(global_object, move(list), move(restricted));
}
// 1.1.3 CollationsOfLocale ( loc ), https://tc39.es/proposal-intl-locale-info/#sec-collations-of-locale
Array* collations_of_locale(GlobalObject& global_object, Locale const& locale_object)
{
// 1. Let restricted be loc.[[Collation]].
Optional<String> restricted = locale_object.has_collation() ? locale_object.collation() : Optional<String> {};
// 2. Let locale be loc.[[Locale]].
auto const& locale = locale_object.locale();
// 3. Assert: locale matches the unicode_locale_id production.
VERIFY(Unicode::parse_unicode_locale_id(locale).has_value());
// 4. Let list be a List of 1 or more unique canonical collation identifiers, which must be lower case String values conforming to the type sequence from UTS 35 Unicode Locale Identifier, section 3.2, sorted in descending preference of those in common use for string comparison in locale. The values "standard" and "search" must be excluded from list.
// FIXME: Retrieve this data from the CLDR when we fully support collation. This matches Intl.supportedValuesOf.
Vector<StringView> list { "default"sv };
// 5. Return ! CreateArrayFromListOrRestricted( list, restricted ).
return create_array_from_list_or_restricted(global_object, move(list), move(restricted));
}
// 1.1.4 HourCyclesOfLocale ( loc ), https://tc39.es/proposal-intl-locale-info/#sec-hour-cycles-of-locale
Array* hour_cycles_of_locale(GlobalObject& global_object, Locale const& locale_object)
{
// 1. Let restricted be loc.[[HourCycle]].
Optional<String> restricted = locale_object.has_hour_cycle() ? locale_object.hour_cycle() : Optional<String> {};
// 2. Let locale be loc.[[Locale]].
auto const& locale = locale_object.locale();
// 3. Assert: locale matches the unicode_locale_id production.
VERIFY(Unicode::parse_unicode_locale_id(locale).has_value());
// 4. Let list be a List of 1 or more unique hour cycle identifiers, which must be lower case String values indicating either the 12-hour format ("h11", "h12") or the 24-hour format ("h23", "h24"), sorted in descending preference of those in common use for date and time formatting in locale.
auto list = Unicode::get_keywords_for_locale(locale, "hc"sv);
// 5. Return ! CreateArrayFromListOrRestricted( list, restricted ).
return create_array_from_list_or_restricted(global_object, move(list), move(restricted));
}
// 1.1.5 NumberingSystemsOfLocale ( loc ), https://tc39.es/proposal-intl-locale-info/#sec-numbering-systems-of-locale
Array* numbering_systems_of_locale(GlobalObject& global_object, Locale const& locale_object)
{
// 1. Let restricted be loc.[[NumberingSystem]].
Optional<String> restricted = locale_object.has_numbering_system() ? locale_object.numbering_system() : Optional<String> {};
// 2. Let locale be loc.[[Locale]].
auto const& locale = locale_object.locale();
// 3. Assert: locale matches the unicode_locale_id production.
VERIFY(Unicode::parse_unicode_locale_id(locale).has_value());
// 4. Let list be a List of 1 or more unique canonical numbering system identifiers, which must be lower case String values conforming to the type sequence from UTS 35 Unicode Locale Identifier, section 3.2, sorted in descending preference of those in common use for formatting numeric values in locale.
auto list = Unicode::get_keywords_for_locale(locale, "nu"sv);
// 5. Return ! CreateArrayFromListOrRestricted( list, restricted ).
return create_array_from_list_or_restricted(global_object, move(list), move(restricted));
}
}