/* * Copyright (c) 2021-2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include "character.h" #include "hilog/log.h" #include "i18n_calendar.h" #include "node_api.h" #include "i18n_addon.h" namespace OHOS { namespace Global { namespace I18n { static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, 0xD001E00, "I18nJs" }; static thread_local napi_ref* g_constructor = nullptr; static thread_local napi_ref* g_brkConstructor = nullptr; static thread_local napi_ref* g_timezoneConstructor = nullptr; static thread_local napi_ref g_indexUtilConstructor = nullptr; static std::unordered_map g_fieldsMap { { "era", UCAL_ERA }, { "year", UCAL_YEAR }, { "month", UCAL_MONTH }, { "week_of_year", UCAL_WEEK_OF_YEAR }, { "week_of_month", UCAL_WEEK_OF_MONTH }, { "date", UCAL_DATE }, { "day_of_year", UCAL_DAY_OF_YEAR }, { "day_of_week", UCAL_DAY_OF_WEEK }, { "day_of_week_in_month", UCAL_DAY_OF_WEEK_IN_MONTH }, { "ap_pm", UCAL_AM_PM }, { "hour", UCAL_HOUR }, { "hour_of_day", UCAL_HOUR_OF_DAY }, { "minute", UCAL_MINUTE }, { "second", UCAL_SECOND }, { "millisecond", UCAL_MILLISECOND }, { "zone_offset", UCAL_ZONE_OFFSET }, { "dst_offset", UCAL_DST_OFFSET }, { "year_woy", UCAL_YEAR_WOY }, { "dow_local", UCAL_DOW_LOCAL }, { "extended_year", UCAL_EXTENDED_YEAR }, { "julian_day", UCAL_JULIAN_DAY }, { "milliseconds_in_day", UCAL_MILLISECONDS_IN_DAY }, { "is_leap_month", UCAL_IS_LEAP_MONTH }, }; static std::unordered_map g_typeMap { { "buddhist", CalendarType::BUDDHIST }, { "chinese", CalendarType::CHINESE }, { "coptic", CalendarType::COPTIC }, { "ethiopic", CalendarType::ETHIOPIC }, { "hebrew", CalendarType::HEBREW }, { "gregory", CalendarType::GREGORY }, { "indian", CalendarType::INDIAN }, { "islamic_civil", CalendarType::ISLAMIC_CIVIL }, { "islamic_tbla", CalendarType::ISLAMIC_TBLA }, { "islamic_umalqura", CalendarType::ISLAMIC_UMALQURA }, { "japanese", CalendarType::JAPANESE }, { "persion", CalendarType::PERSIAN }, }; using namespace OHOS::HiviewDFX; I18nAddon::I18nAddon() : env_(nullptr), wrapper_(nullptr) {} I18nAddon::~I18nAddon() { napi_delete_reference(env_, wrapper_); } void I18nAddon::Destructor(napi_env env, void *nativeObject, void *hint) { if (!nativeObject) { return; } reinterpret_cast(nativeObject)->~I18nAddon(); } napi_value I18nAddon::CreateCharacterObject(napi_env env) { napi_status status = napi_ok; napi_value character = nullptr; status = napi_create_object(env, &character); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to create character object at init"); return nullptr; } napi_property_descriptor characterProperties[] = { DECLARE_NAPI_FUNCTION("isDigit", IsDigitAddon), DECLARE_NAPI_FUNCTION("isSpaceChar", IsSpaceCharAddon), DECLARE_NAPI_FUNCTION("isWhitespace", IsWhiteSpaceAddon), DECLARE_NAPI_FUNCTION("isRTL", IsRTLCharacterAddon), DECLARE_NAPI_FUNCTION("isIdeograph", IsIdeoGraphicAddon), DECLARE_NAPI_FUNCTION("isLetter", IsLetterAddon), DECLARE_NAPI_FUNCTION("isLowerCase", IsLowerCaseAddon), DECLARE_NAPI_FUNCTION("isUpperCase", IsUpperCaseAddon), DECLARE_NAPI_FUNCTION("getType", GetTypeAddon), }; status = napi_define_properties(env, character, sizeof(characterProperties) / sizeof(napi_property_descriptor), characterProperties); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to set properties of character at init"); return nullptr; } return character; } void I18nAddon::CreateInitProperties(napi_property_descriptor *properties) { properties[0] = DECLARE_NAPI_FUNCTION("getSystemLanguages", GetSystemLanguages); // 0 is properties index properties[1] = DECLARE_NAPI_FUNCTION("getSystemCountries", GetSystemCountries); // 1 is properties index properties[2] = DECLARE_NAPI_FUNCTION("isSuggested", IsSuggested); // 2 is properties index properties[3] = DECLARE_NAPI_FUNCTION("getDisplayLanguage", GetDisplayLanguage); // 3 is properties index properties[4] = DECLARE_NAPI_FUNCTION("getDisplayCountry", GetDisplayCountry); // 4 is properties index properties[5] = DECLARE_NAPI_FUNCTION("getSystemLanguage", GetSystemLanguage); // 5 is properties index properties[6] = DECLARE_NAPI_FUNCTION("getSystemRegion", GetSystemRegion); // 6 is properties index properties[7] = DECLARE_NAPI_FUNCTION("getSystemLocale", GetSystemLocale); // 7 is properties index properties[8] = DECLARE_NAPI_FUNCTION("setSystemLanguage", SetSystemLanguage); // 8 is properties index properties[9] = DECLARE_NAPI_FUNCTION("setSystemRegion", SetSystemRegion); // 9 is properties index properties[10] = DECLARE_NAPI_FUNCTION("setSystemLocale", SetSystemLocale); // 10 is properties index properties[11] = DECLARE_NAPI_FUNCTION("getCalendar", GetCalendar); // 11 is properties index properties[12] = DECLARE_NAPI_FUNCTION("isRTL", IsRTL); // 12 is properties index properties[14] = DECLARE_NAPI_FUNCTION("getLineInstance", GetLineInstance); // 14 is properties index properties[15] = DECLARE_NAPI_FUNCTION("getInstance", GetIndexUtil); // 15 is properties index properties[17] = DECLARE_NAPI_FUNCTION("addPreferredLanguage", AddPreferredLanguage); // 17 is properties index // 18 is properties index properties[18] = DECLARE_NAPI_FUNCTION("removePreferredLanguage", RemovePreferredLanguage); // 19 is properties index properties[19] = DECLARE_NAPI_FUNCTION("getPreferredLanguageList", GetPreferredLanguageList); // 20 is properties index properties[20] = DECLARE_NAPI_FUNCTION("getFirstPreferredLanguage", GetFirstPreferredLanguage); // 21 is properties index properties[21] = DECLARE_NAPI_FUNCTION("is24HourClock", Is24HourClock); // 22 is properties index properties[22] = DECLARE_NAPI_FUNCTION("set24HourClock", Set24HourClock); // 23 is properties index properties[23] = DECLARE_NAPI_FUNCTION("getTimeZone", GetI18nTimeZone); } napi_value I18nAddon::Init(napi_env env, napi_value exports) { napi_status status = napi_ok; napi_value util = nullptr; status = napi_create_object(env, &util); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to create util object at init"); return nullptr; } napi_property_descriptor utilProperties[] = { DECLARE_NAPI_FUNCTION("unitConvert", UnitConvert), }; status = napi_define_properties(env, util, sizeof(utilProperties) / sizeof(napi_property_descriptor), utilProperties); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to set properties of util at init"); return nullptr; } napi_value character = CreateCharacterObject(env); if (!character) { return nullptr; } size_t propertiesNums = 24; napi_property_descriptor properties[propertiesNums]; CreateInitProperties(properties); properties[13] = DECLARE_NAPI_PROPERTY("Util", util); // 13 is properties index properties[16] = DECLARE_NAPI_PROPERTY("Character", character); // 16 is properties index status = napi_define_properties(env, exports, propertiesNums, properties); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to set properties at init"); return nullptr; } return exports; } void GetOptionValue(napi_env env, napi_value options, const std::string &optionName, std::string &value) { napi_value optionValue = nullptr; napi_valuetype type = napi_undefined; napi_status status = napi_typeof(env, options, &type); if (status != napi_ok && type != napi_object) { HiLog::Error(LABEL, "Get option failed, option is not an object"); return; } bool hasProperty = false; napi_status propStatus = napi_has_named_property(env, options, optionName.c_str(), &hasProperty); if (propStatus == napi_ok && hasProperty) { status = napi_get_named_property(env, options, optionName.c_str(), &optionValue); if (status == napi_ok) { size_t len; napi_get_value_string_utf8(env, optionValue, nullptr, 0, &len); std::vector optionBuf(len + 1); status = napi_get_value_string_utf8(env, optionValue, optionBuf.data(), len + 1, &len); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to get string item"); return; } value = optionBuf.data(); } } } void GetOptionMap(napi_env env, napi_value option, std::map &map) { if (option != nullptr) { size_t len; napi_get_value_string_utf8(env, option, nullptr, 0, &len); std::vector styleBuf(len + 1); napi_status status = napi_get_value_string_utf8(env, option, styleBuf.data(), len + 1, &len); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to get string item"); return; } map.insert(std::make_pair("unitDisplay", styleBuf.data())); } } napi_value I18nAddon::UnitConvert(napi_env env, napi_callback_info info) { size_t argc = 5; napi_value argv[5] = { 0 }; napi_value thisVar = nullptr; void *data = nullptr; napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); std::string fromUnit; GetOptionValue(env, argv[0], "unit", fromUnit); std::string fromMeasSys; GetOptionValue(env, argv[0], "measureSystem", fromMeasSys); std::string toUnit; GetOptionValue(env, argv[1], "unit", toUnit); std::string toMeasSys; GetOptionValue(env, argv[1], "measureSystem", toMeasSys); double number = 0; napi_get_value_double(env, argv[2], &number); // 2 is the index of value int convertStatus = Convert(number, fromUnit, fromMeasSys, toUnit, toMeasSys); size_t len; napi_get_value_string_utf8(env, argv[3], nullptr, 0, &len); // 3 is the index of value std::vector localeBuf(len + 1); // 3 is the index of value status = napi_get_value_string_utf8(env, argv[3], localeBuf.data(), len + 1, &len); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to get string item"); return nullptr; } std::vector localeTags; localeTags.push_back(localeBuf.data()); std::map map = {}; map.insert(std::make_pair("style", "unit")); if (!convertStatus) { HiLog::Error(LABEL, "Do not support the conversion"); map.insert(std::make_pair("unit", fromUnit)); } else { map.insert(std::make_pair("unit", toUnit)); } // 4 is the index of value GetOptionMap(env, argv[4], map); std::unique_ptr numberFmt = nullptr; numberFmt = std::make_unique(localeTags, map); std::string value = numberFmt->Format(number); napi_value result; status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to create string item"); return nullptr; } return result; } napi_value I18nAddon::IsDigitAddon(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value argv[1] = { 0 }; napi_value thisVar = nullptr; void *data = nullptr; napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); napi_valuetype valueType = napi_valuetype::napi_undefined; napi_typeof(env, argv[0], &valueType); if (valueType != napi_valuetype::napi_string) { napi_throw_type_error(env, nullptr, "Parameter type does not match"); return nullptr; } int32_t code = 0; std::string character = GetString(env, argv[0], code); if (code) { return nullptr; } bool isDigit = IsDigit(character); napi_value result = nullptr; status = napi_get_boolean(env, isDigit, &result); if (status != napi_ok) { HiLog::Error(LABEL, "Create isDigit boolean value failed"); return nullptr; } return result; } napi_value I18nAddon::IsSpaceCharAddon(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value argv[1] = { 0 }; napi_value thisVar = nullptr; void *data = nullptr; napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); napi_valuetype valueType = napi_valuetype::napi_undefined; napi_typeof(env, argv[0], &valueType); if (valueType != napi_valuetype::napi_string) { napi_throw_type_error(env, nullptr, "Parameter type does not match"); return nullptr; } int32_t code = 0; std::string character = GetString(env, argv[0], code); if (code) { return nullptr; } bool isSpaceChar = IsSpaceChar(character); napi_value result = nullptr; status = napi_get_boolean(env, isSpaceChar, &result); if (status != napi_ok) { HiLog::Error(LABEL, "Create isSpaceChar boolean value failed"); return nullptr; } return result; } napi_value I18nAddon::IsWhiteSpaceAddon(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value argv[1] = { 0 }; napi_value thisVar = nullptr; void *data = nullptr; napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); napi_valuetype valueType = napi_valuetype::napi_undefined; napi_typeof(env, argv[0], &valueType); if (valueType != napi_valuetype::napi_string) { napi_throw_type_error(env, nullptr, "Parameter type does not match"); return nullptr; } int32_t code = 0; std::string character = GetString(env, argv[0], code); if (code) { return nullptr; } bool isWhiteSpace = IsWhiteSpace(character); napi_value result = nullptr; status = napi_get_boolean(env, isWhiteSpace, &result); if (status != napi_ok) { HiLog::Error(LABEL, "Create isWhiteSpace boolean value failed"); return nullptr; } return result; } napi_value I18nAddon::IsRTLCharacterAddon(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value argv[1] = { 0 }; napi_value thisVar = nullptr; void *data = nullptr; napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); napi_valuetype valueType = napi_valuetype::napi_undefined; napi_typeof(env, argv[0], &valueType); if (valueType != napi_valuetype::napi_string) { napi_throw_type_error(env, nullptr, "Parameter type does not match"); return nullptr; } int32_t code = 0; std::string character = GetString(env, argv[0], code); if (code) { return nullptr; } bool isRTLCharacter = IsRTLCharacter(character); napi_value result = nullptr; status = napi_get_boolean(env, isRTLCharacter, &result); if (status != napi_ok) { HiLog::Error(LABEL, "Create isRTLCharacter boolean value failed"); return nullptr; } return result; } napi_value I18nAddon::IsIdeoGraphicAddon(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value argv[1] = { 0 }; napi_value thisVar = nullptr; void *data = nullptr; napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); napi_valuetype valueType = napi_valuetype::napi_undefined; napi_typeof(env, argv[0], &valueType); if (valueType != napi_valuetype::napi_string) { napi_throw_type_error(env, nullptr, "Parameter type does not match"); return nullptr; } int32_t code = 0; std::string character = GetString(env, argv[0], code); if (code) { return nullptr; } bool isIdeoGraphic = IsIdeoGraphic(character); napi_value result = nullptr; status = napi_get_boolean(env, isIdeoGraphic, &result); if (status != napi_ok) { HiLog::Error(LABEL, "Create isIdeoGraphic boolean value failed"); return nullptr; } return result; } napi_value I18nAddon::IsLetterAddon(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value argv[1] = { 0 }; napi_value thisVar = nullptr; void *data = nullptr; napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); napi_valuetype valueType = napi_valuetype::napi_undefined; napi_typeof(env, argv[0], &valueType); if (valueType != napi_valuetype::napi_string) { napi_throw_type_error(env, nullptr, "Parameter type does not match"); return nullptr; } int32_t code = 0; std::string character = GetString(env, argv[0], code); if (code) { return nullptr; } bool isLetter = IsLetter(character); napi_value result = nullptr; status = napi_get_boolean(env, isLetter, &result); if (status != napi_ok) { HiLog::Error(LABEL, "Create isLetter boolean value failed"); return nullptr; } return result; } napi_value I18nAddon::IsLowerCaseAddon(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value argv[1] = { 0 }; napi_value thisVar = nullptr; void *data = nullptr; napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); napi_valuetype valueType = napi_valuetype::napi_undefined; napi_typeof(env, argv[0], &valueType); if (valueType != napi_valuetype::napi_string) { napi_throw_type_error(env, nullptr, "Parameter type does not match"); return nullptr; } int32_t code = 0; std::string character = GetString(env, argv[0], code); if (code) { return nullptr; } bool isLowerCase = IsLowerCase(character); napi_value result = nullptr; status = napi_get_boolean(env, isLowerCase, &result); if (status != napi_ok) { HiLog::Error(LABEL, "Create isLowerCase boolean value failed"); return nullptr; } return result; } napi_value I18nAddon::IsUpperCaseAddon(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value argv[1] = { 0 }; napi_value thisVar = nullptr; void *data = nullptr; napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); napi_valuetype valueType = napi_valuetype::napi_undefined; napi_typeof(env, argv[0], &valueType); if (valueType != napi_valuetype::napi_string) { napi_throw_type_error(env, nullptr, "Parameter type does not match"); return nullptr; } int32_t code = 0; std::string character = GetString(env, argv[0], code); if (code) { return nullptr; } bool isUpperCase = IsUpperCase(character); napi_value result = nullptr; status = napi_get_boolean(env, isUpperCase, &result); if (status != napi_ok) { HiLog::Error(LABEL, "Create isUpperCase boolean value failed"); return nullptr; } return result; } napi_value I18nAddon::GetTypeAddon(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value argv[1] = { 0 }; napi_value thisVar = nullptr; void *data = nullptr; napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); napi_valuetype valueType = napi_valuetype::napi_undefined; napi_typeof(env, argv[0], &valueType); if (valueType != napi_valuetype::napi_string) { napi_throw_type_error(env, nullptr, "Parameter type does not match"); return nullptr; } int32_t code = 0; std::string character = GetString(env, argv[0], code); if (code) { return nullptr; } std::string type = GetType(character); napi_value result = nullptr; status = napi_create_string_utf8(env, type.c_str(), NAPI_AUTO_LENGTH, &result); if (status != napi_ok) { HiLog::Error(LABEL, "Create getType string value failed"); return nullptr; } return result; } napi_value I18nAddon::GetSystemLanguages(napi_env env, napi_callback_info info) { std::vector systemLanguages; LocaleConfig::GetSystemLanguages(systemLanguages); napi_value result = nullptr; napi_status status = napi_create_array_with_length(env, systemLanguages.size(), &result); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to create array"); return nullptr; } for (size_t i = 0; i < systemLanguages.size(); i++) { napi_value value = nullptr; status = napi_create_string_utf8(env, systemLanguages[i].c_str(), NAPI_AUTO_LENGTH, &value); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to create string item"); return nullptr; } status = napi_set_element(env, result, i, value); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to set array item"); return nullptr; } } return result; } napi_value I18nAddon::GetSystemCountries(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value argv[1] = { 0 }; napi_value thisVar = nullptr; void *data = nullptr; napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); size_t len = 0; napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len); std::vector localeBuf(len + 1); status = napi_get_value_string_utf8(env, argv[0], localeBuf.data(), len + 1, &len); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to get string item"); return nullptr; } std::vector systemCountries; LocaleConfig::GetSystemCountries(systemCountries); napi_value result = nullptr; status = napi_create_array_with_length(env, systemCountries.size(), &result); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to create array"); return nullptr; } for (size_t i = 0; i < systemCountries.size(); i++) { napi_value value = nullptr; status = napi_create_string_utf8(env, systemCountries[i].c_str(), NAPI_AUTO_LENGTH, &value); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to create string item"); return nullptr; } status = napi_set_element(env, result, i, value); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to set array item"); return nullptr; } } return result; } napi_value I18nAddon::GetSystemLanguage(napi_env env, napi_callback_info info) { std::string value = LocaleConfig::GetSystemLanguage(); napi_value result = nullptr; napi_status status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to create string item"); return nullptr; } return result; } napi_value I18nAddon::GetSystemRegion(napi_env env, napi_callback_info info) { std::string value = LocaleConfig::GetSystemRegion(); napi_value result = nullptr; napi_status status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to create string item"); return nullptr; } return result; } napi_value I18nAddon::GetSystemLocale(napi_env env, napi_callback_info info) { std::string value = LocaleConfig::GetSystemLocale(); napi_value result = nullptr; napi_status status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to create string item"); return nullptr; } return result; } napi_value I18nAddon::GetDisplayLanguage(napi_env env, napi_callback_info info) { // Need to get three parameters to get the display Language. size_t argc = 3; napi_value argv[3] = { 0 }; napi_value thisVar = nullptr; void *data = nullptr; napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); size_t len = 0; napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len); std::vector localeBuf(len + 1); status = napi_get_value_string_utf8(env, argv[0], localeBuf.data(), len + 1, &len); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to get string item"); return nullptr; } napi_get_value_string_utf8(env, argv[1], nullptr, 0, &len); std::vector displayLocaleBuf(len + 1); status = napi_get_value_string_utf8(env, argv[1], displayLocaleBuf.data(), len + 1, &len); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to get string item"); return nullptr; } bool sentenceCase = true; int sentenceCaseIndex = 2; if (argv[sentenceCaseIndex] != nullptr) { napi_get_value_bool(env, argv[sentenceCaseIndex], &sentenceCase); } std::string value = LocaleConfig::GetDisplayLanguage(localeBuf.data(), displayLocaleBuf.data(), sentenceCase); napi_value result = nullptr; status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to create string item"); return nullptr; } return result; } napi_value I18nAddon::GetDisplayCountry(napi_env env, napi_callback_info info) { // Need to get three parameters to get the display country. size_t argc = 3; napi_value argv[3] = { 0 }; napi_value thisVar = nullptr; void *data = nullptr; napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); size_t len = 0; napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len); std::vector localeBuf(len + 1); status = napi_get_value_string_utf8(env, argv[0], localeBuf.data(), len + 1, &len); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to get string item"); return nullptr; } napi_get_value_string_utf8(env, argv[1], nullptr, 0, &len); std::vector displayLocaleBuf(len + 1); status = napi_get_value_string_utf8(env, argv[1], displayLocaleBuf.data(), len + 1, &len); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to get string item"); return nullptr; } bool sentenceCase = true; int sentenceCaseIndex = 2; if (argv[sentenceCaseIndex] != nullptr) { napi_get_value_bool(env, argv[sentenceCaseIndex], &sentenceCase); } std::string value = LocaleConfig::GetDisplayRegion(localeBuf.data(), displayLocaleBuf.data(), sentenceCase); napi_value result = nullptr; status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to create string item"); return nullptr; } return result; } napi_value I18nAddon::IsSuggested(napi_env env, napi_callback_info info) { // Need to get two parameters to check is suggested or not. size_t argc = 2; napi_value argv[2] = { 0 }; napi_value thisVar = nullptr; void *data = nullptr; napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); size_t len = 0; napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len); std::vector languageBuf(len + 1); status = napi_get_value_string_utf8(env, argv[0], languageBuf.data(), len + 1, &len); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to get string item"); return nullptr; } bool isSuggested = false; if (argv[1] != nullptr) { napi_get_value_string_utf8(env, argv[1], nullptr, 0, &len); std::vector regionBuf(len + 1); status = napi_get_value_string_utf8(env, argv[1], regionBuf.data(), len + 1, &len); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to get string item"); return nullptr; } isSuggested = LocaleConfig::IsSuggested(languageBuf.data(), regionBuf.data()); } else { isSuggested = LocaleConfig::IsSuggested(languageBuf.data()); } napi_value result = nullptr; status = napi_get_boolean(env, isSuggested, &result); if (status != napi_ok) { HiLog::Error(LABEL, "Create case first boolean value failed"); return nullptr; } return result; } napi_value I18nAddon::SetSystemLanguage(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value argv[1] = { 0 }; napi_value thisVar = nullptr; void *data = nullptr; napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); size_t len = 0; napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len); std::vector languageBuf(len + 1); status = napi_get_value_string_utf8(env, argv[0], languageBuf.data(), len + 1, &len); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to get string item"); return nullptr; } bool success = LocaleConfig::SetSystemLanguage(languageBuf.data()); napi_value result = nullptr; status = napi_get_boolean(env, success, &result); if (status != napi_ok) { HiLog::Error(LABEL, "Create set system language boolean value failed"); return nullptr; } return result; } napi_value I18nAddon::SetSystemRegion(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value argv[1] = { 0 }; napi_value thisVar = nullptr; void *data = nullptr; napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); size_t len = 0; napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len); std::vector regionBuf(len + 1); status = napi_get_value_string_utf8(env, argv[0], regionBuf.data(), len + 1, &len); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to get string item"); return nullptr; } bool success = LocaleConfig::SetSystemRegion(regionBuf.data()); napi_value result = nullptr; status = napi_get_boolean(env, success, &result); if (status != napi_ok) { HiLog::Error(LABEL, "Create set system language boolean value failed"); return nullptr; } return result; } napi_value I18nAddon::SetSystemLocale(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value argv[1] = { 0 }; napi_value thisVar = nullptr; void *data = nullptr; napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); size_t len = 0; napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len); std::vector localeBuf(len + 1); status = napi_get_value_string_utf8(env, argv[0], localeBuf.data(), len + 1, &len); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to get string item"); return nullptr; } bool success = LocaleConfig::SetSystemLocale(localeBuf.data()); napi_value result = nullptr; status = napi_get_boolean(env, success, &result); if (status != napi_ok) { HiLog::Error(LABEL, "Create set system language boolean value failed"); return nullptr; } return result; } napi_value I18nAddon::IsRTL(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value argv[1] = { 0 }; napi_value thisVar = nullptr; void *data = nullptr; napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); size_t len = 0; napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len); std::vector localeBuf(len + 1); status = napi_get_value_string_utf8(env, argv[0], localeBuf.data(), len + 1, &len); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to get string item"); return nullptr; } bool isRTL = LocaleConfig::IsRTL(localeBuf.data()); napi_value result = nullptr; status = napi_get_boolean(env, isRTL, &result); if (status != napi_ok) { HiLog::Error(LABEL, "IsRTL failed"); return nullptr; } return result; } napi_value I18nAddon::InitPhoneNumberFormat(napi_env env, napi_value exports) { napi_status status = napi_ok; napi_property_descriptor properties[] = { DECLARE_NAPI_FUNCTION("isValidNumber", IsValidPhoneNumber), DECLARE_NAPI_FUNCTION("format", FormatPhoneNumber) }; napi_value constructor; status = napi_define_class(env, "PhoneNumberFormat", NAPI_AUTO_LENGTH, PhoneNumberFormatConstructor, nullptr, sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor); if (status != napi_ok) { HiLog::Error(LABEL, "Define class failed when InitPhoneNumberFormat"); return nullptr; } status = napi_set_named_property(env, exports, "PhoneNumberFormat", constructor); if (status != napi_ok) { HiLog::Error(LABEL, "Set property failed when InitPhoneNumberFormat"); return nullptr; } return exports; } void GetOptionValue(napi_env env, napi_value options, const std::string &optionName, std::map &map) { napi_value optionValue = nullptr; napi_valuetype type = napi_undefined; napi_status status = napi_typeof(env, options, &type); if (status != napi_ok && type != napi_object) { HiLog::Error(LABEL, "Get option failed, option is not an object"); return; } bool hasProperty = false; napi_status propStatus = napi_has_named_property(env, options, optionName.c_str(), &hasProperty); if (propStatus == napi_ok && hasProperty) { status = napi_get_named_property(env, options, optionName.c_str(), &optionValue); if (status == napi_ok) { size_t len = 0; napi_get_value_string_utf8(env, optionValue, nullptr, 0, &len); std::vector optionBuf(len + 1); status = napi_get_value_string_utf8(env, optionValue, optionBuf.data(), len + 1, &len); map.insert(make_pair(optionName, optionBuf.data())); } } } napi_value I18nAddon::PhoneNumberFormatConstructor(napi_env env, napi_callback_info info) { size_t argc = 2; napi_value argv[2] = { 0 }; napi_value thisVar = nullptr; void *data = nullptr; napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); napi_valuetype valueType = napi_valuetype::napi_undefined; napi_typeof(env, argv[0], &valueType); if (valueType != napi_valuetype::napi_string) { napi_throw_type_error(env, nullptr, "Parameter type does not match"); return nullptr; } size_t len = 0; status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len); if (status != napi_ok) { HiLog::Error(LABEL, "Get country tag length failed"); return nullptr; } std::vector country (len + 1); status = napi_get_value_string_utf8(env, argv[0], country.data(), len + 1, &len); if (status != napi_ok) { HiLog::Error(LABEL, "Get country tag failed"); return nullptr; } std::map options; GetOptionValue(env, argv[1], "type", options); std::unique_ptr obj = nullptr; obj = std::make_unique(); if (!obj) { HiLog::Error(LABEL, "Create I18nAddon failed"); return nullptr; } status = napi_wrap(env, thisVar, reinterpret_cast(obj.get()), I18nAddon::Destructor, nullptr, &obj->wrapper_); if (status != napi_ok) { HiLog::Error(LABEL, "Wrap I18nAddon failed"); return nullptr; } if (!obj->InitPhoneNumberFormatContext(env, info, country.data(), options)) { return nullptr; } obj.release(); return thisVar; } bool I18nAddon::InitPhoneNumberFormatContext(napi_env env, napi_callback_info info, const std::string &country, const std::map &options) { napi_value global = nullptr; napi_status status = napi_get_global(env, &global); if (status != napi_ok) { HiLog::Error(LABEL, "Get global failed"); return false; } env_ = env; phonenumberfmt_ = std::make_unique(country, options); return phonenumberfmt_ != nullptr; } napi_value I18nAddon::IsValidPhoneNumber(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value argv[1] = { 0 }; napi_value thisVar = nullptr; void *data = nullptr; napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); napi_valuetype valueType = napi_valuetype::napi_undefined; napi_typeof(env, argv[0], &valueType); if (valueType != napi_valuetype::napi_string) { napi_throw_type_error(env, nullptr, "Parameter type does not match"); return nullptr; } size_t len = 0; napi_status status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len); if (status != napi_ok) { HiLog::Error(LABEL, "Get phone number length failed"); return nullptr; } std::vector buf(len + 1); status = napi_get_value_string_utf8(env, argv[0], buf.data(), len + 1, &len); if (status != napi_ok) { HiLog::Error(LABEL, "Get phone number failed"); return nullptr; } I18nAddon *obj = nullptr; status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); if (status != napi_ok || !obj || !obj->phonenumberfmt_) { HiLog::Error(LABEL, "GetPhoneNumberFormat object failed"); return nullptr; } bool isValid = obj->phonenumberfmt_->isValidPhoneNumber(buf.data()); napi_value result = nullptr; status = napi_get_boolean(env, isValid, &result); if (status != napi_ok) { HiLog::Error(LABEL, "Create boolean failed"); return nullptr; } return result; } napi_value I18nAddon::FormatPhoneNumber(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value argv[1] = { 0 }; napi_value thisVar = nullptr; void *data = nullptr; napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); napi_valuetype valueType = napi_valuetype::napi_undefined; napi_typeof(env, argv[0], &valueType); if (valueType != napi_valuetype::napi_string) { napi_throw_type_error(env, nullptr, "Parameter type does not match"); return nullptr; } size_t len = 0; napi_status status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len); if (status != napi_ok) { HiLog::Error(LABEL, "Get phone number length failed"); return nullptr; } std::vector buf(len + 1); status = napi_get_value_string_utf8(env, argv[0], buf.data(), len + 1, &len); if (status != napi_ok) { HiLog::Error(LABEL, "Get phone number failed"); return nullptr; } I18nAddon *obj = nullptr; status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); if (status != napi_ok || !obj || !obj->phonenumberfmt_) { HiLog::Error(LABEL, "Get PhoneNumberFormat object failed"); return nullptr; } std::string formattedPhoneNumber = obj->phonenumberfmt_->format(buf.data()); napi_value result = nullptr; status = napi_create_string_utf8(env, formattedPhoneNumber.c_str(), NAPI_AUTO_LENGTH, &result); if (status != napi_ok) { HiLog::Error(LABEL, "Create format phone number failed"); return nullptr; } return result; } std::string I18nAddon::GetString(napi_env &env, napi_value &value, int32_t &code) { size_t len = 0; napi_status status = napi_get_value_string_utf8(env, value, nullptr, 0, &len); if (status != napi_ok) { HiLog::Error(LABEL, "Get string failed"); code = 1; return ""; } std::vector buf(len + 1); status = napi_get_value_string_utf8(env, value, buf.data(), len + 1, &len); if (status != napi_ok) { HiLog::Error(LABEL, "Create string failed"); code = 1; return ""; } return buf.data(); } napi_value I18nAddon::InitI18nCalendar(napi_env env, napi_value exports) { napi_status status = napi_ok; napi_property_descriptor properties[] = { DECLARE_NAPI_FUNCTION("setTime", SetTime), DECLARE_NAPI_FUNCTION("set", Set), DECLARE_NAPI_FUNCTION("getTimeZone", GetTimeZone), DECLARE_NAPI_FUNCTION("setTimeZone", SetTimeZone), DECLARE_NAPI_FUNCTION("getFirstDayOfWeek", GetFirstDayOfWeek), DECLARE_NAPI_FUNCTION("setFirstDayOfWeek", SetFirstDayOfWeek), DECLARE_NAPI_FUNCTION("getMinimalDaysInFirstWeek", GetMinimalDaysInFirstWeek), DECLARE_NAPI_FUNCTION("setMinimalDaysInFirstWeek", SetMinimalDaysInFirstWeek), DECLARE_NAPI_FUNCTION("get", Get), DECLARE_NAPI_FUNCTION("getDisplayName", GetDisplayName), DECLARE_NAPI_FUNCTION("isWeekend", IsWeekend) }; napi_value constructor = nullptr; status = napi_define_class(env, "I18nCalendar", NAPI_AUTO_LENGTH, CalendarConstructor, nullptr, sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to define class at Init"); return nullptr; } g_constructor = new (std::nothrow) napi_ref; if (!g_constructor) { HiLog::Error(LABEL, "Failed to create ref at init"); return nullptr; } status = napi_create_reference(env, constructor, 1, g_constructor); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to create reference at init"); return nullptr; } return exports; } napi_value I18nAddon::CalendarConstructor(napi_env env, napi_callback_info info) { size_t argc = 2; napi_value argv[2] = { 0 }; argv[0] = nullptr; argv[1] = nullptr; napi_value thisVar = nullptr; void *data = nullptr; napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); if (status != napi_ok) { return nullptr; } napi_valuetype valueType = napi_valuetype::napi_undefined; napi_typeof(env, argv[0], &valueType); if (valueType != napi_valuetype::napi_string) { napi_throw_type_error(env, nullptr, "Parameter type does not match"); return nullptr; } int32_t code = 0; std::string localeTag = GetString(env, argv[0], code); if (code) { return nullptr; } CalendarType type = GetCalendarType(env, argv[1]); std::unique_ptr obj = nullptr; obj = std::make_unique(); if (!obj) { HiLog::Error(LABEL, "Create I18nAddon failed"); return nullptr; } status = napi_wrap(env, thisVar, reinterpret_cast(obj.get()), I18nAddon::Destructor, nullptr, &obj->wrapper_); if (status != napi_ok) { HiLog::Error(LABEL, "Wrap II18nAddon failed"); return nullptr; } if (!obj->InitCalendarContext(env, info, localeTag, type)) { return nullptr; } obj.release(); return thisVar; } CalendarType I18nAddon::GetCalendarType(napi_env env, napi_value value) { CalendarType type = CalendarType::UNDEFINED; if (value != nullptr) { napi_valuetype valueType = napi_valuetype::napi_undefined; napi_typeof(env, value, &valueType); if (valueType != napi_valuetype::napi_string) { napi_throw_type_error(env, nullptr, "Parameter type does not match"); return type; } int32_t code = 0; std::string calendarType = GetString(env, value, code); if (code) { return type; } if (g_typeMap.find(calendarType) != g_typeMap.end()) { type = g_typeMap[calendarType]; } } return type; } bool I18nAddon::InitCalendarContext(napi_env env, napi_callback_info info, const std::string &localeTag, CalendarType type) { calendar_ = std::make_unique(localeTag, type); return calendar_ != nullptr; } napi_value I18nAddon::GetCalendar(napi_env env, napi_callback_info info) { size_t argc = 2; // retrieve 2 arguments napi_value argv[2] = { 0 }; argv[0] = nullptr; argv[1] = nullptr; napi_value thisVar = nullptr; void *data = nullptr; napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); napi_value constructor = nullptr; napi_status status = napi_get_reference_value(env, *g_constructor, &constructor); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to create reference at GetCalendar"); return nullptr; } if (!argv[1]) { status = napi_create_string_utf8(env, "", NAPI_AUTO_LENGTH, argv + 1); if (status != napi_ok) { return nullptr; } } napi_value result = nullptr; status = napi_new_instance(env, constructor, 2, argv, &result); // 2 arguments if (status != napi_ok) { HiLog::Error(LABEL, "Get calendar create instance failed"); return nullptr; } return result; } napi_value I18nAddon::GetDate(napi_env env, napi_value value) { if (!value) { return nullptr; } napi_value funcGetDateInfo = nullptr; napi_status status = napi_get_named_property(env, value, "valueOf", &funcGetDateInfo); if (status != napi_ok) { HiLog::Error(LABEL, "Get method valueOf failed"); return nullptr; } napi_value ret_value = nullptr; status = napi_call_function(env, value, funcGetDateInfo, 0, nullptr, &ret_value); if (status != napi_ok) { HiLog::Error(LABEL, "Get milliseconds failed"); return nullptr; } return ret_value; } void I18nAddon::SetMilliseconds(napi_env env, napi_value value) { if (!value) { return; } double milliseconds = 0; napi_valuetype valueType = napi_valuetype::napi_undefined; napi_typeof(env, value, &valueType); if (valueType != napi_valuetype::napi_number) { napi_throw_type_error(env, nullptr, "Parameter type does not match"); return; } napi_status status = napi_get_value_double(env, value, &milliseconds); if (status != napi_ok) { HiLog::Error(LABEL, "Retrieve milliseconds failed"); return; } if (calendar_ != nullptr) { calendar_->SetTime(milliseconds); } } napi_value I18nAddon::Set(napi_env env, napi_callback_info info) { size_t argc = 6; // Set may have 6 arguments napi_value argv[6] = { 0 }; for (size_t i = 0; i < argc; ++i) { argv[i] = nullptr; } napi_value thisVar = nullptr; void *data = nullptr; napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); napi_valuetype valueType = napi_valuetype::napi_undefined; napi_status status = napi_ok; int32_t times[3] = { 0 }; // There are at least 3 arguments. for (int i = 0; i < 3; ++i) { // There are at least 3 arguments. napi_typeof(env, argv[i], &valueType); if (valueType != napi_valuetype::napi_number) { napi_throw_type_error(env, nullptr, "Parameter type does not match"); return nullptr; } status = napi_get_value_int32(env, argv[i], times + i); if (status != napi_ok) { HiLog::Error(LABEL, "Retrieve time value failed"); return nullptr; } } I18nAddon *obj = nullptr; status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); if (status != napi_ok || !obj || !obj->calendar_) { HiLog::Error(LABEL, "Get calendar object failed"); return nullptr; } obj->calendar_->Set(times[0], times[1], times[2]); // 2 is the index of date obj->SetField(env, argv[3], UCalendarDateFields::UCAL_HOUR_OF_DAY); // 3 is the index of hour obj->SetField(env, argv[4], UCalendarDateFields::UCAL_MINUTE); // 4 is the index of minute obj->SetField(env, argv[5], UCalendarDateFields::UCAL_SECOND); // 5 is the index of second return nullptr; } napi_value I18nAddon::SetTime(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value argv[1] = { 0 }; argv[0] = nullptr; napi_value thisVar = nullptr; void *data = nullptr; napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); if (!argv[0]) { return nullptr; } I18nAddon *obj = nullptr; napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); if (status != napi_ok || !obj || !obj->calendar_) { HiLog::Error(LABEL, "Get calendar object failed"); return nullptr; } napi_valuetype type = napi_valuetype::napi_undefined; status = napi_typeof(env, argv[0], &type); if (status != napi_ok) { return nullptr; } if (type == napi_valuetype::napi_number) { obj->SetMilliseconds(env, argv[0]); return nullptr; } else { napi_value val = GetDate(env, argv[0]); if (!val) { return nullptr; } obj->SetMilliseconds(env, val); return nullptr; } } void I18nAddon::SetField(napi_env env, napi_value value, UCalendarDateFields field) { if (!value) { return; } int32_t val = 0; napi_valuetype valueType = napi_valuetype::napi_undefined; napi_typeof(env, value, &valueType); if (valueType != napi_valuetype::napi_number) { napi_throw_type_error(env, nullptr, "Parameter type does not match"); return; } napi_status status = napi_get_value_int32(env, value, &val); if (status != napi_ok) { HiLog::Error(LABEL, "Retrieve field failed"); return; } if (calendar_ != nullptr) { calendar_->Set(field, val); } } napi_value I18nAddon::SetTimeZone(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value argv[1] = { 0 }; argv[0] = nullptr; napi_value thisVar = nullptr; void *data = nullptr; napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); napi_valuetype valueType = napi_valuetype::napi_undefined; napi_typeof(env, argv[0], &valueType); if (valueType != napi_valuetype::napi_string) { napi_throw_type_error(env, nullptr, "Parameter type does not match"); return nullptr; } size_t len = 0; napi_status status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len); if (status != napi_ok) { HiLog::Error(LABEL, "Get timezone length failed"); return nullptr; } std::vector buf(len + 1); status = napi_get_value_string_utf8(env, argv[0], buf.data(), len + 1, &len); if (status != napi_ok) { HiLog::Error(LABEL, "Get timezone failed"); return nullptr; } std::string timezone(buf.data()); I18nAddon *obj = nullptr; status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); if (status != napi_ok || !obj || !obj->calendar_) { HiLog::Error(LABEL, "Get calendar object failed"); return nullptr; } obj->calendar_->SetTimeZone(timezone); return nullptr; } napi_value I18nAddon::GetTimeZone(napi_env env, napi_callback_info info) { size_t argc = 0; napi_value *argv = nullptr; napi_value thisVar = nullptr; void *data = nullptr; napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); I18nAddon *obj = nullptr; napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); if (status != napi_ok || !obj || !obj->calendar_) { HiLog::Error(LABEL, "Get calendar object failed"); return nullptr; } std::string temp = obj->calendar_->GetTimeZone(); napi_value result = nullptr; status = napi_create_string_utf8(env, temp.c_str(), NAPI_AUTO_LENGTH, &result); if (status != napi_ok) { HiLog::Error(LABEL, "Create timezone string failed"); return nullptr; } return result; } napi_value I18nAddon::GetFirstDayOfWeek(napi_env env, napi_callback_info info) { size_t argc = 0; napi_value *argv = nullptr; napi_value thisVar = nullptr; void *data = nullptr; napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); I18nAddon *obj = nullptr; napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); if (status != napi_ok || !obj || !obj->calendar_) { HiLog::Error(LABEL, "Get calendar object failed"); return nullptr; } int32_t temp = obj->calendar_->GetFirstDayOfWeek(); napi_value result = nullptr; status = napi_create_int32(env, temp, &result); if (status != napi_ok) { HiLog::Error(LABEL, "Create int32 failed"); return nullptr; } return result; } napi_value I18nAddon::GetMinimalDaysInFirstWeek(napi_env env, napi_callback_info info) { size_t argc = 0; napi_value *argv = nullptr; napi_value thisVar = nullptr; void *data = nullptr; napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); I18nAddon *obj = nullptr; napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); if (status != napi_ok || !obj || !obj->calendar_) { HiLog::Error(LABEL, "Get calendar object failed"); return nullptr; } int32_t temp = obj->calendar_->GetMinimalDaysInFirstWeek(); napi_value result = nullptr; status = napi_create_int32(env, temp, &result); if (status != napi_ok) { HiLog::Error(LABEL, "Create int32 failed"); return nullptr; } return result; } napi_value I18nAddon::SetFirstDayOfWeek(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value argv[1] = { 0 }; argv[0] = nullptr; napi_value thisVar = nullptr; void *data = nullptr; napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); napi_valuetype valueType = napi_valuetype::napi_undefined; napi_typeof(env, argv[0], &valueType); if (valueType != napi_valuetype::napi_number) { napi_throw_type_error(env, nullptr, "Parameter type does not match"); return nullptr; } int32_t value = 0; napi_status status = napi_get_value_int32(env, argv[0], &value); if (status != napi_ok) { HiLog::Error(LABEL, "Get int32 failed"); return nullptr; } I18nAddon *obj = nullptr; status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); if (status != napi_ok || !obj || !obj->calendar_) { HiLog::Error(LABEL, "Get calendar object failed"); return nullptr; } obj->calendar_->SetFirstDayOfWeek(value); return nullptr; } napi_value I18nAddon::SetMinimalDaysInFirstWeek(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value argv[1] = { 0 }; argv[0] = nullptr; napi_value thisVar = nullptr; void *data = nullptr; napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); napi_valuetype valueType = napi_valuetype::napi_undefined; napi_typeof(env, argv[0], &valueType); if (valueType != napi_valuetype::napi_number) { napi_throw_type_error(env, nullptr, "Parameter type does not match"); return nullptr; } int32_t value = 0; napi_status status = napi_get_value_int32(env, argv[0], &value); if (status != napi_ok) { HiLog::Error(LABEL, "Get int32 failed"); return nullptr; } I18nAddon *obj = nullptr; status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); if (status != napi_ok || !obj || !obj->calendar_) { HiLog::Error(LABEL, "Get calendar object failed"); return nullptr; } obj->calendar_->SetMinimalDaysInFirstWeek(value); return nullptr; } napi_value I18nAddon::Get(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value argv[1] = { 0 }; argv[0] = nullptr; napi_value thisVar = nullptr; void *data = nullptr; napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); napi_valuetype valueType = napi_valuetype::napi_undefined; napi_typeof(env, argv[0], &valueType); if (valueType != napi_valuetype::napi_string) { napi_throw_type_error(env, nullptr, "Parameter type does not match"); return nullptr; } size_t len = 0; napi_status status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len); if (status != napi_ok) { HiLog::Error(LABEL, "Get field length failed"); return nullptr; } std::vector buf(len + 1); status = napi_get_value_string_utf8(env, argv[0], buf.data(), len + 1, &len); if (status != napi_ok) { HiLog::Error(LABEL, "Get field failed"); return nullptr; } std::string field(buf.data()); if (g_fieldsMap.find(field) == g_fieldsMap.end()) { HiLog::Error(LABEL, "Invalid field"); return nullptr; } I18nAddon *obj = nullptr; status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); if (status != napi_ok || !obj || !obj->calendar_) { HiLog::Error(LABEL, "Get calendar object failed"); return nullptr; } int32_t value = obj->calendar_->Get(g_fieldsMap[field]); napi_value result = nullptr; status = napi_create_int32(env, value, &result); if (status != napi_ok) { HiLog::Error(LABEL, "Create int32 failed"); return nullptr; } return result; } napi_value I18nAddon::IsWeekend(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value argv[1] = { 0 }; argv[0] = nullptr; napi_value thisVar = nullptr; void *data = nullptr; napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); I18nAddon *obj = nullptr; bool isWeekEnd = false; napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); do { if (status != napi_ok || !obj || !obj->calendar_) { HiLog::Error(LABEL, "Get calendar object failed"); break; } if (!argv[0]) { isWeekEnd = obj->calendar_->IsWeekend(); } else { napi_value funcGetDateInfo = nullptr; status = napi_get_named_property(env, argv[0], "valueOf", &funcGetDateInfo); if (status != napi_ok) { HiLog::Error(LABEL, "Get method now failed"); break; } napi_value value = nullptr; status = napi_call_function(env, argv[0], funcGetDateInfo, 0, nullptr, &value); if (status != napi_ok) { HiLog::Error(LABEL, "Get milliseconds failed"); break; } double milliseconds = 0; status = napi_get_value_double(env, value, &milliseconds); if (status != napi_ok) { HiLog::Error(LABEL, "Retrieve milliseconds failed"); break; } UErrorCode error = U_ZERO_ERROR; isWeekEnd = obj->calendar_->IsWeekend(milliseconds, error); } } while (false); napi_value result = nullptr; status = napi_get_boolean(env, isWeekEnd, &result); if (status != napi_ok) { HiLog::Error(LABEL, "Create boolean failed"); return nullptr; } return result; } napi_value I18nAddon::GetDisplayName(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value argv[1] = { 0 }; argv[0] = nullptr; napi_value thisVar = nullptr; void *data = nullptr; napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); napi_valuetype valueType = napi_valuetype::napi_undefined; napi_typeof(env, argv[0], &valueType); if (valueType != napi_valuetype::napi_string) { napi_throw_type_error(env, nullptr, "Parameter type does not match"); return nullptr; } int32_t code = 0; std::string localeTag = GetString(env, argv[0], code); if (code) { return nullptr; } I18nAddon *obj = nullptr; napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); if (status != napi_ok || !obj || !obj->calendar_) { HiLog::Error(LABEL, "Get calendar object failed"); return nullptr; } if (!obj->calendar_) { return nullptr; } std::string name = obj->calendar_->GetDisplayName(localeTag); napi_value result = nullptr; status = napi_create_string_utf8(env, name.c_str(), NAPI_AUTO_LENGTH, &result); if (status != napi_ok) { HiLog::Error(LABEL, "Create calendar name string failed"); return nullptr; } return result; } napi_value I18nAddon::InitIndexUtil(napi_env env, napi_value exports) { napi_property_descriptor properties[] = { DECLARE_NAPI_FUNCTION("getIndexList", GetIndexList), DECLARE_NAPI_FUNCTION("addLocale", AddLocale), DECLARE_NAPI_FUNCTION("getIndex", GetIndex) }; napi_value constructor = nullptr; napi_status status = napi_define_class(env, "IndexUtil", NAPI_AUTO_LENGTH, IndexUtilConstructor, nullptr, sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor); if (status != napi_ok) { HiLog::Error(LABEL, "Define class failed when InitPhoneNumberFormat"); return nullptr; } status = napi_create_reference(env, constructor, 1, &g_indexUtilConstructor); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to create reference at init"); return nullptr; } return exports; } napi_value I18nAddon::BreakIteratorConstructor(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value argv[1] = { nullptr }; napi_value thisVar = nullptr; void *data = nullptr; napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); if (status != napi_ok) { return nullptr; } napi_valuetype valueType = napi_valuetype::napi_undefined; napi_typeof(env, argv[0], &valueType); if (valueType != napi_valuetype::napi_string) { napi_throw_type_error(env, nullptr, "Parameter type does not match"); return nullptr; } int32_t code = 0; std::string localeTag = GetString(env, argv[0], code); if (code) { return nullptr; } std::unique_ptr obj = nullptr; obj = std::make_unique(); if (!obj) { HiLog::Error(LABEL, "Create I18nAddon failed"); return nullptr; } status = napi_wrap(env, thisVar, reinterpret_cast(obj.get()), I18nAddon::Destructor, nullptr, &obj->wrapper_); if (status != napi_ok) { HiLog::Error(LABEL, "Wrap II18nAddon failed"); return nullptr; } obj->brkiter_ = std::make_unique(localeTag); if (!obj->brkiter_) { HiLog::Error(LABEL, "Wrap BreakIterator failed"); return nullptr; } obj.release(); return thisVar; } napi_value I18nAddon::InitBreakIterator(napi_env env, napi_value exports) { napi_status status = napi_ok; napi_property_descriptor properties[] = { DECLARE_NAPI_FUNCTION("current", Current), DECLARE_NAPI_FUNCTION("first", First), DECLARE_NAPI_FUNCTION("last", Last), DECLARE_NAPI_FUNCTION("next", Next), DECLARE_NAPI_FUNCTION("previous", Previous), DECLARE_NAPI_FUNCTION("setLineBreakText", SetText), DECLARE_NAPI_FUNCTION("following", Following), DECLARE_NAPI_FUNCTION("getLineBreakText", GetText), DECLARE_NAPI_FUNCTION("isBoundary", IsBoundary), }; napi_value constructor = nullptr; status = napi_define_class(env, "BreakIterator", NAPI_AUTO_LENGTH, BreakIteratorConstructor, nullptr, sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to define class BreakIterator at Init"); return nullptr; } g_brkConstructor = new (std::nothrow) napi_ref; if (!g_brkConstructor) { HiLog::Error(LABEL, "Failed to create brkiterator ref at init"); return nullptr; } status = napi_create_reference(env, constructor, 1, g_brkConstructor); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to create reference g_brkConstructor at init"); return nullptr; } return exports; } napi_value I18nAddon::GetLineInstance(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value argv[1] = { nullptr }; napi_value thisVar = nullptr; void *data = nullptr; napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); napi_value constructor = nullptr; napi_status status = napi_get_reference_value(env, *g_brkConstructor, &constructor); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to create reference at GetLineInstance"); return nullptr; } if (!argv[0]) { return nullptr; } napi_value result = nullptr; status = napi_new_instance(env, constructor, 1, argv, &result); // 1 arguments if (status != napi_ok) { HiLog::Error(LABEL, "GetLineInstance create instance failed"); return nullptr; } return result; } napi_value I18nAddon::Current(napi_env env, napi_callback_info info) { size_t argc = 0; napi_value *argv = nullptr; napi_value thisVar = nullptr; void *data = nullptr; napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); I18nAddon *obj = nullptr; napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); if (status != napi_ok || !obj || !obj->brkiter_) { HiLog::Error(LABEL, "Get BreakIterator object failed"); return nullptr; } int value = obj->brkiter_->current(); napi_value result = nullptr; status = napi_create_int32(env, value, &result); if (status != napi_ok) { HiLog::Error(LABEL, "Create int32_t value failed"); return nullptr; } return result; } napi_value I18nAddon::First(napi_env env, napi_callback_info info) { size_t argc = 0; napi_value *argv = nullptr; napi_value thisVar = nullptr; void *data = nullptr; napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); I18nAddon *obj = nullptr; napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); if (status != napi_ok || !obj || !obj->brkiter_) { HiLog::Error(LABEL, "Get BreakIterator object failed"); return nullptr; } int value = obj->brkiter_->first(); napi_value result = nullptr; status = napi_create_int32(env, value, &result); if (status != napi_ok) { HiLog::Error(LABEL, "Create int32_t value failed"); return nullptr; } return result; } napi_value I18nAddon::Last(napi_env env, napi_callback_info info) { size_t argc = 0; napi_value *argv = nullptr; napi_value thisVar = nullptr; void *data = nullptr; napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); I18nAddon *obj = nullptr; napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); if (status != napi_ok || !obj || !obj->brkiter_) { HiLog::Error(LABEL, "Get BreakIterator object failed"); return nullptr; } int value = obj->brkiter_->last(); napi_value result = nullptr; status = napi_create_int32(env, value, &result); if (status != napi_ok) { HiLog::Error(LABEL, "Create int32_t value failed"); return nullptr; } return result; } napi_value I18nAddon::Previous(napi_env env, napi_callback_info info) { size_t argc = 0; napi_value *argv = nullptr; napi_value thisVar = nullptr; void *data = nullptr; napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); I18nAddon *obj = nullptr; napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); if (status != napi_ok || !obj || !obj->brkiter_) { HiLog::Error(LABEL, "Get BreakIterator object failed"); return nullptr; } int value = obj->brkiter_->previous(); napi_value result = nullptr; status = napi_create_int32(env, value, &result); if (status != napi_ok) { HiLog::Error(LABEL, "Create int32_t value failed"); return nullptr; } return result; } napi_value I18nAddon::Next(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value argv[1] = { nullptr }; napi_value thisVar = nullptr; void *data = nullptr; napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); I18nAddon *obj = nullptr; napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); if (status != napi_ok || !obj || !obj->brkiter_) { HiLog::Error(LABEL, "Get BreakIterator object failed"); return nullptr; } int value = 1; if (argv[0] != nullptr) { napi_valuetype valueType = napi_valuetype::napi_undefined; napi_typeof(env, argv[0], &valueType); if (valueType != napi_valuetype::napi_number) { napi_throw_type_error(env, nullptr, "Parameter type does not match"); return nullptr; } status = napi_get_value_int32(env, argv[0], &value); if (status != napi_ok) { HiLog::Error(LABEL, "Retrieve next value failed"); return nullptr; } } value = obj->brkiter_->next(value); napi_value result = nullptr; status = napi_create_int32(env, value, &result); if (status != napi_ok) { HiLog::Error(LABEL, "Create int32_t value failed"); return nullptr; } return result; } napi_value I18nAddon::SetText(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value argv[1] = { nullptr }; napi_value thisVar = nullptr; void *data = nullptr; napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); I18nAddon *obj = nullptr; napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); if (status != napi_ok || !obj || !obj->brkiter_) { HiLog::Error(LABEL, "Get BreakIterator object failed"); return nullptr; } if (!argv[0]) { return nullptr; } napi_valuetype valueType = napi_valuetype::napi_undefined; napi_typeof(env, argv[0], &valueType); if (valueType != napi_valuetype::napi_string) { napi_throw_type_error(env, nullptr, "Parameter type does not match"); return nullptr; } size_t len = 0; status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len); if (status != napi_ok) { HiLog::Error(LABEL, "Get field length failed"); return nullptr; } std::vector buf(len + 1); status = napi_get_value_string_utf8(env, argv[0], buf.data(), len + 1, &len); if (status != napi_ok) { HiLog::Error(LABEL, "Get string value failed"); return nullptr; } obj->brkiter_->setText(buf.data()); return nullptr; } napi_value I18nAddon::GetText(napi_env env, napi_callback_info info) { size_t argc = 0; napi_value *argv = nullptr; napi_value thisVar = nullptr; void *data = nullptr; napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); I18nAddon *obj = nullptr; napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); if (status != napi_ok || !obj || !obj->brkiter_) { HiLog::Error(LABEL, "Get BreakIterator object failed"); return nullptr; } napi_value value = nullptr; std::string temp; obj->brkiter_->getText(temp); status = napi_create_string_utf8(env, temp.c_str(), NAPI_AUTO_LENGTH, &value); if (status != napi_ok) { HiLog::Error(LABEL, "Get field length failed"); return nullptr; } return value; } napi_value I18nAddon::Following(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value argv[1] = { nullptr }; napi_value thisVar = nullptr; void *data = nullptr; napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); I18nAddon *obj = nullptr; napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); if (status != napi_ok || !obj || !obj->brkiter_) { HiLog::Error(LABEL, "Get BreakIterator object failed"); return nullptr; } if (!argv[0]) { return nullptr; } napi_valuetype valueType = napi_valuetype::napi_undefined; napi_typeof(env, argv[0], &valueType); if (valueType != napi_valuetype::napi_number) { napi_throw_type_error(env, nullptr, "Parameter type does not match"); return nullptr; } int value; status = napi_get_value_int32(env, argv[0], &value); if (status != napi_ok) { HiLog::Error(LABEL, "Retrieve following value failed"); return nullptr; } value = obj->brkiter_->following(value); napi_value result = nullptr; status = napi_create_int32(env, value, &result); if (status != napi_ok) { HiLog::Error(LABEL, "Create int32_t value failed"); return nullptr; } return result; } napi_value I18nAddon::IsBoundary(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value argv[1] = { nullptr }; napi_value thisVar = nullptr; void *data = nullptr; napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); I18nAddon *obj = nullptr; napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); if (status != napi_ok || !obj || !obj->brkiter_) { HiLog::Error(LABEL, "Get BreakIterator object failed"); return nullptr; } if (!argv[0]) { return nullptr; } napi_valuetype valueType = napi_valuetype::napi_undefined; int value; napi_typeof(env, argv[0], &valueType); if (valueType != napi_valuetype::napi_number) { napi_throw_type_error(env, nullptr, "Parameter type does not match"); return nullptr; } status = napi_get_value_int32(env, argv[0], &value); if (status != napi_ok) { HiLog::Error(LABEL, "Retrieve following value failed"); return nullptr; } bool boundary = obj->brkiter_->isBoundary(value); napi_value result = nullptr; status = napi_get_boolean(env, boundary, &result); if (status != napi_ok) { HiLog::Error(LABEL, "Create boolean failed"); return nullptr; } return result; } napi_value I18nAddon::IndexUtilConstructor(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value argv[1] = { 0 }; napi_value thisVar = nullptr; void *data = nullptr; napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); std::string localeTag = ""; if (argv[0] != nullptr) { napi_valuetype valueType = napi_valuetype::napi_undefined; napi_typeof(env, argv[0], &valueType); if (valueType != napi_valuetype::napi_string) { napi_throw_type_error(env, nullptr, "Parameter type does not match"); return nullptr; } size_t len = 0; status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len); if (status != napi_ok) { HiLog::Error(LABEL, "Get locale length failed"); return nullptr; } std::vector localeBuf(len + 1); status = napi_get_value_string_utf8(env, argv[0], localeBuf.data(), len + 1, &len); if (status != napi_ok) { HiLog::Error(LABEL, "Get locale failed"); return nullptr; } localeTag = localeBuf.data(); } std::unique_ptr obj = nullptr; obj = std::make_unique(); if (!obj) { HiLog::Error(LABEL, "Create I18nAddon failed"); return nullptr; } status = napi_wrap(env, thisVar, reinterpret_cast(obj.get()), I18nAddon::Destructor, nullptr, &obj->wrapper_); if (status != napi_ok) { HiLog::Error(LABEL, "Wrap II18nAddon failed"); return nullptr; } if (!obj->InitIndexUtilContext(env, info, localeTag)) { return nullptr; } obj.release(); return thisVar; } bool I18nAddon::InitIndexUtilContext(napi_env env, napi_callback_info info, const std::string &localeTag) { napi_value global = nullptr; napi_status status = napi_get_global(env, &global); if (status != napi_ok) { HiLog::Error(LABEL, "Get global failed"); return false; } env_ = env; indexUtil_ = std::make_unique(localeTag); return indexUtil_ != nullptr; } napi_value I18nAddon::GetIndexUtil(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value argv[1] = { 0 }; napi_value thisVar = nullptr; void *data = nullptr; napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); napi_value constructor = nullptr; napi_status status = napi_get_reference_value(env, g_indexUtilConstructor, &constructor); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to create reference at GetIndexUtil"); return nullptr; } napi_value result = nullptr; if (!argv[0]) { status = napi_new_instance(env, constructor, 0, argv, &result); } else { status = napi_new_instance(env, constructor, 1, argv, &result); } if (status != napi_ok) { HiLog::Error(LABEL, "Get calendar create instance failed"); return nullptr; } return result; } napi_value I18nAddon::GetIndexList(napi_env env, napi_callback_info info) { size_t argc = 0; napi_value argv[0]; napi_value thisVar = nullptr; void *data = nullptr; napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); I18nAddon *obj = nullptr; napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); if (status != napi_ok || !obj || !obj->indexUtil_) { HiLog::Error(LABEL, "GetPhoneNumberFormat object failed"); return nullptr; } std::vector indexList = obj->indexUtil_->GetIndexList(); napi_value result = nullptr; status = napi_create_array_with_length(env, indexList.size(), &result); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to create array"); return nullptr; } for (size_t i = 0; i < indexList.size(); i++) { napi_value element = nullptr; status = napi_create_string_utf8(env, indexList[i].c_str(), NAPI_AUTO_LENGTH, &element); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to create string item"); return nullptr; } status = napi_set_element(env, result, i, element); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to set array item"); return nullptr; } } return result; } napi_value I18nAddon::AddLocale(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value argv[1] = { 0 }; napi_value thisVar = nullptr; void *data = nullptr; napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); napi_valuetype valueType = napi_valuetype::napi_undefined; napi_typeof(env, argv[0], &valueType); if (valueType != napi_valuetype::napi_string) { napi_throw_type_error(env, nullptr, "Parameter type does not match"); return nullptr; } size_t len = 0; napi_status status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len); if (status != napi_ok) { HiLog::Error(LABEL, "Get locale length failed"); return nullptr; } std::vector buf(len + 1); status = napi_get_value_string_utf8(env, argv[0], buf.data(), len + 1, &len); if (status != napi_ok) { HiLog::Error(LABEL, "Get locale failed"); return nullptr; } I18nAddon *obj = nullptr; status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); if (status != napi_ok || !obj || !obj->indexUtil_) { HiLog::Error(LABEL, "Get IndexUtil object failed"); return nullptr; } obj->indexUtil_->AddLocale(buf.data()); return nullptr; } napi_value I18nAddon::GetIndex(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value argv[1] = { 0 }; napi_value thisVar = nullptr; void *data = nullptr; napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); napi_valuetype valueType = napi_valuetype::napi_undefined; napi_typeof(env, argv[0], &valueType); if (valueType != napi_valuetype::napi_string) { napi_throw_type_error(env, nullptr, "Parameter type does not match"); return nullptr; } size_t len = 0; napi_status status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len); if (status != napi_ok) { HiLog::Error(LABEL, "Get String length failed"); return nullptr; } std::vector buf(len + 1); status = napi_get_value_string_utf8(env, argv[0], buf.data(), len + 1, &len); if (status != napi_ok) { HiLog::Error(LABEL, "Get String failed"); return nullptr; } I18nAddon *obj = nullptr; status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); if (status != napi_ok || !obj || !obj->indexUtil_) { HiLog::Error(LABEL, "Get IndexUtil object failed"); return nullptr; } std::string index = obj->indexUtil_->GetIndex(buf.data()); napi_value result = nullptr; status = napi_create_string_utf8(env, index.c_str(), NAPI_AUTO_LENGTH, &result); if (status != napi_ok) { HiLog::Error(LABEL, "GetIndex Failed"); return nullptr; } return result; } napi_value I18nAddon::Is24HourClock(napi_env env, napi_callback_info info) { bool is24HourClock = LocaleConfig::Is24HourClock(); napi_value result = nullptr; napi_status status = napi_get_boolean(env, is24HourClock, &result); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to create boolean item"); return nullptr; } return result; } napi_value I18nAddon::Set24HourClock(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value argv[1] = { 0 }; napi_value thisVar = nullptr; void *data = nullptr; napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); bool option = false; status = napi_get_value_bool(env, argv[0], &option); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to get boolean item"); return nullptr; } bool success = LocaleConfig::Set24HourClock(option); napi_value result = nullptr; status = napi_get_boolean(env, success, &result); if (status != napi_ok) { HiLog::Error(LABEL, "Create set 24HourClock boolean value failed"); return nullptr; } return result; } napi_value I18nAddon::AddPreferredLanguage(napi_env env, napi_callback_info info) { size_t argc = 2; napi_value argv[2] = { 0 }; napi_value thisVar = nullptr; void *data = nullptr; napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); napi_valuetype valueType = napi_valuetype::napi_undefined; napi_typeof(env, argv[0], &valueType); if (valueType != napi_valuetype::napi_string) { napi_throw_type_error(env, nullptr, "addPreferredLanguage: first parameter type does not match"); return nullptr; } size_t len = 0; status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len); if (status != napi_ok) { HiLog::Error(LABEL, "addPreferredLanguage: get language length failed"); return nullptr; } std::vector language(len + 1); status = napi_get_value_string_utf8(env, argv[0], language.data(), len + 1, &len); if (status != napi_ok) { HiLog::Error(LABEL, "addPreferrdLanguage: get language failed"); return nullptr; } int index = 1000000; if (argv[1] != nullptr) { status = napi_get_value_int32(env, argv[1], &index); } if (status != napi_ok) { HiLog::Error(LABEL, "addPreferrdLanguage: get index failed"); return nullptr; } bool success = PreferredLanguage::AddPreferredLanguage(language.data(), index); napi_value result = nullptr; status = napi_get_boolean(env, success, &result); if (status != napi_ok) { HiLog::Error(LABEL, "addPreferrdLanguage: create boolean result failed"); return nullptr; } return result; } napi_value I18nAddon::RemovePreferredLanguage(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value argv[1] = { 0 }; napi_value thisVar = nullptr; void *data = nullptr; napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); napi_valuetype valueType = napi_valuetype::napi_undefined; napi_typeof(env, argv[0], &valueType); if (valueType != napi_valuetype::napi_number) { napi_throw_type_error(env, nullptr, "removePreferredLanguage: parameter type does not match"); return nullptr; } int index = 1000000; status = napi_get_value_int32(env, argv[0], &index); if (status != napi_ok) { HiLog::Error(LABEL, "removePreferrdLanguage: get index failed"); return nullptr; } bool success = PreferredLanguage::RemovePreferredLanguage(index); napi_value result = nullptr; status = napi_get_boolean(env, success, &result); if (status != napi_ok) { HiLog::Error(LABEL, "removePreferrdLanguage: create boolean result failed"); return nullptr; } return result; } napi_value I18nAddon::GetPreferredLanguageList(napi_env env, napi_callback_info info) { std::vector languageList = PreferredLanguage::GetPreferredLanguageList(); napi_value result = nullptr; napi_status status = napi_ok; status = napi_create_array_with_length(env, languageList.size(), &result); if (status != napi_ok) { HiLog::Error(LABEL, "getPreferrdLanguageList: create array failed"); return nullptr; } for (size_t i = 0; i < languageList.size(); i++) { napi_value value = nullptr; status = napi_create_string_utf8(env, languageList[i].c_str(), NAPI_AUTO_LENGTH, &value); if (status != napi_ok) { HiLog::Error(LABEL, "getPreferrdLanguageList: create string failed"); return nullptr; } status = napi_set_element(env, result, i, value); if (status != napi_ok) { HiLog::Error(LABEL, "GetPreferredLanguageList: set array item failed"); return nullptr; } } return result; } napi_value I18nAddon::GetFirstPreferredLanguage(napi_env env, napi_callback_info info) { std::string language = PreferredLanguage::GetFirstPreferredLanguage(); napi_value result = nullptr; napi_status status = napi_ok; status = napi_create_string_utf8(env, language.c_str(), NAPI_AUTO_LENGTH, &result); if (status != napi_ok) { HiLog::Error(LABEL, "getFirstPreferrdLanguage: create string result failed"); return nullptr; } return result; } napi_value I18nAddon::InitI18nTimeZone(napi_env env, napi_value exports) { napi_status status = napi_ok; napi_property_descriptor properties[] = { DECLARE_NAPI_FUNCTION("getID", GetID), DECLARE_NAPI_FUNCTION("getDisplayName", GetTimeZoneDisplayName), DECLARE_NAPI_FUNCTION("getRawOffset", GetRawOffset), DECLARE_NAPI_FUNCTION("getOffset", GetOffset), }; napi_value constructor = nullptr; status = napi_define_class(env, "TimeZone", NAPI_AUTO_LENGTH, I18nTimeZoneConstructor, nullptr, sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to define class TimeZone at Init"); return nullptr; } g_timezoneConstructor = new (std::nothrow) napi_ref; if (!g_timezoneConstructor) { HiLog::Error(LABEL, "Failed to create TimeZone ref at init"); return nullptr; } status = napi_create_reference(env, constructor, 1, g_timezoneConstructor); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to create reference g_timezoneConstructor at init"); return nullptr; } return exports; } napi_value I18nAddon::I18nTimeZoneConstructor(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value argv[1] = { nullptr }; napi_value thisVar = nullptr; void *data = nullptr; napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); if (status != napi_ok) { return nullptr; } std::string zoneID = ""; if (argv[0] != nullptr) { napi_valuetype valueType = napi_valuetype::napi_undefined; napi_typeof(env, argv[0], &valueType); if (valueType != napi_valuetype::napi_string) { napi_throw_type_error(env, nullptr, "Parameter type does not match"); return nullptr; } int32_t code = 0; zoneID = GetString(env, argv[0], code); if (code != 0) { return nullptr; } } std::unique_ptr obj = nullptr; obj = std::make_unique(); if (!obj) { HiLog::Error(LABEL, "Create I18nAddon failed"); return nullptr; } status = napi_wrap(env, thisVar, reinterpret_cast(obj.get()), I18nAddon::Destructor, nullptr, &obj->wrapper_); if (status != napi_ok) { HiLog::Error(LABEL, "Wrap II18nAddon failed"); return nullptr; } obj->timezone_ = std::make_unique(zoneID); if (!obj->timezone_) { HiLog::Error(LABEL, "Wrap TimeZone failed"); return nullptr; } obj.release(); return thisVar; } napi_value I18nAddon::GetI18nTimeZone(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value argv[1] = { nullptr }; napi_value thisVar = nullptr; void *data = nullptr; napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); napi_value constructor = nullptr; napi_status status = napi_get_reference_value(env, *g_timezoneConstructor, &constructor); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to create reference at GetTimeZoneInstance"); return nullptr; } napi_value result = nullptr; if (!argv[0]) { status = napi_new_instance(env, constructor, 0, nullptr, &result); // 1 arguments } else { status = napi_new_instance(env, constructor, 1, argv, &result); // 1 arguments } if (status != napi_ok) { HiLog::Error(LABEL, "GetTimeZone create instance failed"); return nullptr; } return result; } napi_value I18nAddon::GetID(napi_env env, napi_callback_info info) { size_t argc = 0; napi_value *argv = nullptr; napi_value thisVar = nullptr; void *data = nullptr; napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); I18nAddon *obj = nullptr; napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); if (status != napi_ok || !obj || !obj->timezone_) { HiLog::Error(LABEL, "Get TimeZone object failed"); return nullptr; } std::string result = obj->timezone_->GetID(); napi_value value = nullptr; status = napi_create_string_utf8(env, result.c_str(), NAPI_AUTO_LENGTH, &value); if (status != napi_ok) { HiLog::Error(LABEL, "Create result failed"); return nullptr; } return value; } bool I18nAddon::GetStringFromJS(napi_env env, napi_value argv, std::string &jsString) { size_t len = 0; napi_status status = napi_get_value_string_utf8(env, argv, nullptr, 0, &len); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to get string length"); return false; } std::vector argvBuf(len + 1); status = napi_get_value_string_utf8(env, argv, argvBuf.data(), len + 1, &len); if (status != napi_ok) { HiLog::Error(LABEL, "Failed to get string item"); return false; } jsString = argvBuf.data(); return true; } int32_t I18nAddon::GetParameter(napi_env env, napi_value *argv, std::string &localeStr, bool &isDST) { if (!argv[0]) { return 0; // 0 represents no parameter. } napi_status status = napi_ok; if (!argv[1]) { napi_valuetype valueType = napi_valuetype::napi_undefined; napi_typeof(env, argv[0], &valueType); if (valueType == napi_valuetype::napi_string) { bool valid = GetStringFromJS(env, argv[0], localeStr); if (!valid) { return -1; // -1 represents Invalid parameter. } return 1; // 1 represents one string parameter. } else if (valueType == napi_valuetype::napi_boolean) { status = napi_get_value_bool(env, argv[0], &isDST); if (status != napi_ok) { return -1; // -1 represents Invalid parameter. } return 2; // 2 represents one boolean parameter. } else { return -1; // -1 represents Invalid parameter. } } napi_valuetype valueType0 = napi_valuetype::napi_undefined; napi_valuetype valueType1 = napi_valuetype::napi_undefined; napi_typeof(env, argv[0], &valueType0); // 0 represents first parameter napi_typeof(env, argv[1], &valueType1); // 0 represents second parameter if (valueType0 != napi_valuetype::napi_string || valueType1 != napi_valuetype::napi_boolean) { return -1; // -1 represents Invalid parameter. } bool valid = GetStringFromJS(env, argv[0], localeStr); if (!valid) { return -1; // -1 represents Invalid parameter. } status = napi_get_value_bool(env, argv[1], &isDST); if (status != napi_ok) { return -1; // -1 represents Invalid parameter. } return 3; // 3 represents one string parameter and one bool parameter. } napi_value I18nAddon::GetTimeZoneDisplayName(napi_env env, napi_callback_info info) { size_t argc = 2; napi_value argv[2] = { 0 }; napi_value thisVar = nullptr; void *data = nullptr; napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); I18nAddon *obj = nullptr; status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); if (status != napi_ok || !obj || !obj->timezone_) { HiLog::Error(LABEL, "Get TimeZone object failed"); return nullptr; } std::string locale; bool isDST = false; int32_t parameterStatus = GetParameter(env, argv, locale, isDST); std::string result; if (parameterStatus == -1) { // -1 represents Invalid parameter. napi_throw_type_error(env, nullptr, "Parameter type does not match"); return nullptr; } else if (parameterStatus == 0) { result = obj->timezone_->GetDisplayName(); } else if (parameterStatus == 1) { // 1 represents one string parameter. result = obj->timezone_->GetDisplayName(locale); } else if (parameterStatus == 2) { // 2 represents one boolean parameter. result = obj->timezone_->GetDisplayName(isDST); } else { result = obj->timezone_->GetDisplayName(locale, isDST); } napi_value value = nullptr; status = napi_create_string_utf8(env, result.c_str(), NAPI_AUTO_LENGTH, &value); if (status != napi_ok) { HiLog::Error(LABEL, "Create result failed"); return nullptr; } return value; } napi_value I18nAddon::GetOffset(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value argv[1] = { 0 }; napi_value thisVar = nullptr; void *data = nullptr; napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); double date = 0; if (argv[0]) { napi_valuetype valueType = napi_valuetype::napi_undefined; napi_typeof(env, argv[0], &valueType); if (valueType != napi_valuetype::napi_number) { HiLog::Error(LABEL, "Invalid parameter type"); return nullptr; } status = napi_get_value_double(env, argv[0], &date); if (status != napi_ok) { HiLog::Error(LABEL, "Get parameter date failed"); return nullptr; } } else { auto time = std::chrono::system_clock::now(); auto since_epoch = time.time_since_epoch(); auto millis = std::chrono::duration_cast(since_epoch); date = (double)millis.count(); } I18nAddon *obj = nullptr; status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); if (status != napi_ok || !obj || !obj->timezone_) { HiLog::Error(LABEL, "Get TimeZone object failed"); return nullptr; } int32_t result = obj->timezone_->GetOffset(date); napi_value value = nullptr; status = napi_create_int32(env, result, &value); if (status != napi_ok) { HiLog::Error(LABEL, "Create result failed"); return nullptr; } return value; } napi_value I18nAddon::GetRawOffset(napi_env env, napi_callback_info info) { size_t argc = 0; napi_value *argv = nullptr; napi_value thisVar = nullptr; void *data = nullptr; napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); I18nAddon *obj = nullptr; napi_status status = napi_unwrap(env, thisVar, reinterpret_cast(&obj)); if (status != napi_ok || !obj || !obj->timezone_) { HiLog::Error(LABEL, "Get TimeZone object failed"); return nullptr; } int32_t result = obj->timezone_->GetRawOffset(); napi_value value = nullptr; status = napi_create_int32(env, result, &value); if (status != napi_ok) { HiLog::Error(LABEL, "Create result failed"); return nullptr; } return value; } napi_value Init(napi_env env, napi_value exports) { napi_value val = I18nAddon::Init(env, exports); val = I18nAddon::InitPhoneNumberFormat(env, val); val = I18nAddon::InitBreakIterator(env, val); val = I18nAddon::InitI18nCalendar(env, val); val = I18nAddon::InitIndexUtil(env, val); return I18nAddon::InitI18nTimeZone(env, val); } static napi_module g_i18nModule = { .nm_version = 1, .nm_flags = 0, .nm_filename = nullptr, .nm_register_func = Init, .nm_modname = "i18n", .nm_priv = ((void *)0), .reserved = { 0 } }; extern "C" __attribute__((constructor)) void I18nRegister() { napi_module_register(&g_i18nModule); } } // namespace I18n } // namespace Global } // namespace OHOS