1/* 2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15#include <unordered_map> 16#include <vector> 17 18#include "error_util.h" 19#include "i18n_hilog.h" 20#include "holiday_manager_addon.h" 21#include "entity_recognizer_addon.h" 22#include "i18n_calendar_addon.h" 23#include "i18n_normalizer_addon.h" 24#include "i18n_system_addon.h" 25#include "i18n_timezone_addon.h" 26#include "i18n_unicode_addon.h" 27#include "js_utils.h" 28#include "locale_info.h" 29#include "locale_matcher.h" 30#include "node_api.h" 31#include "system_locale_manager_addon.h" 32#include "unicode/datefmt.h" 33#include "unicode/locid.h" 34#include "unicode/smpdtfmt.h" 35#include "unicode/translit.h" 36#include "utils.h" 37#include "variable_convertor.h" 38#include "i18n_addon.h" 39#include "date_time_sequence.h" 40 41namespace OHOS { 42namespace Global { 43namespace I18n { 44static thread_local napi_ref* g_brkConstructor = nullptr; 45static thread_local napi_ref g_indexUtilConstructor = nullptr; 46static thread_local napi_ref* g_transConstructor = nullptr; 47 48I18nAddon::I18nAddon() : env_(nullptr) {} 49 50I18nAddon::~I18nAddon() 51{ 52 PhoneNumberFormat::CloseDynamicHandler(); 53} 54 55void I18nAddon::Destructor(napi_env env, void *nativeObject, void *hint) 56{ 57 if (!nativeObject) { 58 return; 59 } 60 delete reinterpret_cast<I18nAddon *>(nativeObject); 61 nativeObject = nullptr; 62} 63 64napi_value I18nAddon::InitI18nUtil(napi_env env, napi_value exports) 65{ 66 napi_property_descriptor properties[] = { 67 DECLARE_NAPI_STATIC_FUNCTION("unitConvert", UnitConvert), 68 DECLARE_NAPI_STATIC_FUNCTION("getDateOrder", GetDateOrder), 69 DECLARE_NAPI_STATIC_FUNCTION("getTimePeriodName", GetTimePeriodName), 70 DECLARE_NAPI_STATIC_FUNCTION("getBestMatchLocale", GetBestMatchLocale), 71 DECLARE_NAPI_STATIC_FUNCTION("getThreeLetterLanguage", GetThreeLetterLanguage), 72 DECLARE_NAPI_STATIC_FUNCTION("getThreeLetterRegion", GetThreeLetterRegion) 73 }; 74 napi_value constructor = nullptr; 75 napi_status status = napi_define_class(env, "I18NUtil", NAPI_AUTO_LENGTH, JSUtils::DefaultConstructor, nullptr, 76 sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor); 77 if (status != napi_ok) { 78 HILOG_ERROR_I18N("InitI18nUtil: Define class failed when InitI18NUtil."); 79 return nullptr; 80 } 81 82 status = napi_set_named_property(env, exports, "I18NUtil", constructor); 83 if (status != napi_ok) { 84 HILOG_ERROR_I18N("InitI18nUtil: Set property failed when InitI18NUtil."); 85 return nullptr; 86 } 87 return exports; 88} 89 90napi_value I18nAddon::Init(napi_env env, napi_value exports) 91{ 92 napi_status initStatus = napi_ok; 93 napi_property_descriptor properties[] = { 94 DECLARE_NAPI_FUNCTION("getDisplayLanguage", I18nSystemAddon::GetDisplayLanguage), 95 DECLARE_NAPI_FUNCTION("getDisplayCountry", I18nSystemAddon::GetDisplayCountry), 96 DECLARE_NAPI_FUNCTION("getSystemLanguage", I18nSystemAddon::GetSystemLanguage), 97 DECLARE_NAPI_FUNCTION("getSystemRegion", I18nSystemAddon::GetSystemRegion), 98 DECLARE_NAPI_FUNCTION("getSystemLocale", I18nSystemAddon::GetSystemLocale), 99 DECLARE_NAPI_FUNCTION("getCalendar", I18nCalendarAddon::GetCalendar), 100 DECLARE_NAPI_FUNCTION("isRTL", IsRTL), 101 DECLARE_NAPI_FUNCTION("getLineInstance", GetLineInstance), 102 DECLARE_NAPI_FUNCTION("getInstance", GetIndexUtil), 103 DECLARE_NAPI_FUNCTION("addPreferredLanguage", I18nSystemAddon::AddPreferredLanguage), 104 DECLARE_NAPI_FUNCTION("removePreferredLanguage", I18nSystemAddon::RemovePreferredLanguage), 105 DECLARE_NAPI_FUNCTION("getPreferredLanguageList", I18nSystemAddon::GetPreferredLanguageList), 106 DECLARE_NAPI_FUNCTION("getFirstPreferredLanguage", I18nSystemAddon::GetFirstPreferredLanguage), 107 DECLARE_NAPI_FUNCTION("is24HourClock", I18nSystemAddon::Is24HourClock), 108 DECLARE_NAPI_FUNCTION("set24HourClock", I18nSystemAddon::Set24HourClock), 109 DECLARE_NAPI_FUNCTION("getTimeZone", I18nTimeZoneAddon::GetI18nTimeZone), 110 DECLARE_NAPI_PROPERTY("NormalizerMode", I18nNormalizerAddon::CreateI18NNormalizerModeEnum(env, initStatus)) 111 }; 112 initStatus = napi_define_properties(env, exports, sizeof(properties) / sizeof(napi_property_descriptor), 113 properties); 114 if (initStatus != napi_ok) { 115 HILOG_ERROR_I18N("Failed to set properties at init"); 116 return nullptr; 117 } 118 return exports; 119} 120 121void GetOptionMap(napi_env env, napi_value option, std::map<std::string, std::string> &map) 122{ 123 if (VariableConvertor::CheckNapiValueType(env, option)) { 124 size_t len; 125 napi_get_value_string_utf8(env, option, nullptr, 0, &len); 126 std::vector<char> styleBuf(len + 1); 127 napi_status status = napi_get_value_string_utf8(env, option, styleBuf.data(), len + 1, &len); 128 if (status != napi_ok) { 129 HILOG_ERROR_I18N("GetOptionMap: Failed to get string item"); 130 return; 131 } 132 map.insert(std::make_pair("unitDisplay", styleBuf.data())); 133 } 134} 135 136napi_value I18nAddon::UnitConvert(napi_env env, napi_callback_info info) 137{ 138 size_t argc = 5; 139 napi_value argv[5] = { 0 }; 140 napi_value thisVar = nullptr; 141 void *data = nullptr; 142 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 143 if (status != napi_ok) { 144 return nullptr; 145 } 146 std::string fromUnit; 147 VariableConvertor::GetOptionValue(env, argv[0], "unit", fromUnit); 148 std::string fromMeasSys; 149 VariableConvertor::GetOptionValue(env, argv[0], "measureSystem", fromMeasSys); 150 std::string toUnit; 151 VariableConvertor::GetOptionValue(env, argv[1], "unit", toUnit); 152 std::string toMeasSys; 153 VariableConvertor::GetOptionValue(env, argv[1], "measureSystem", toMeasSys); 154 double number = 0; 155 napi_get_value_double(env, argv[2], &number); // 2 is the index of value 156 int convertStatus = Convert(number, fromUnit, fromMeasSys, toUnit, toMeasSys); 157 size_t len; 158 napi_get_value_string_utf8(env, argv[3], nullptr, 0, &len); // 3 is the index of value 159 std::vector<char> localeBuf(len + 1); 160 // 3 is the index of value 161 status = napi_get_value_string_utf8(env, argv[3], localeBuf.data(), len + 1, &len); 162 if (status != napi_ok) { 163 return nullptr; 164 } 165 std::vector<std::string> localeTags; 166 localeTags.push_back(localeBuf.data()); 167 std::map<std::string, std::string> map = {}; 168 map.insert(std::make_pair("style", "unit")); 169 if (!convertStatus) { 170 map.insert(std::make_pair("unit", fromUnit)); 171 } else { 172 map.insert(std::make_pair("unit", toUnit)); 173 } 174 // 4 is the index of value 175 GetOptionMap(env, argv[4], map); 176 std::unique_ptr<NumberFormat> numberFmt = nullptr; 177 numberFmt = std::make_unique<NumberFormat>(localeTags, map); 178 std::string value = numberFmt->Format(number); 179 napi_value result; 180 status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result); 181 if (status != napi_ok) { 182 HILOG_ERROR_I18N("UnitConvert: Failed to create string item"); 183 return nullptr; 184 } 185 return result; 186} 187 188napi_value I18nAddon::GetDateOrder(napi_env env, napi_callback_info info) 189{ 190 size_t argc = 1; 191 napi_value argv[1] = { 0 }; 192 napi_value thisVar = nullptr; 193 void *data = nullptr; 194 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 195 if (status != napi_ok) { 196 return nullptr; 197 } 198 size_t len = 0; 199 napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len); 200 std::vector<char> languageBuf(len + 1); 201 status = napi_get_value_string_utf8(env, argv[0], languageBuf.data(), len + 1, &len); 202 if (status != napi_ok) { 203 HILOG_ERROR_I18N("Failed to get locale string for GetDateOrder"); 204 return nullptr; 205 } 206 std::string languageTag = languageBuf.data(); 207 std::string value = DateTimeSequence::GetDateOrder(languageTag); 208 napi_value result; 209 status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result); 210 if (status != napi_ok) { 211 HILOG_ERROR_I18N("GetDateOrder Failed to create string item"); 212 return nullptr; 213 } 214 return result; 215} 216 217napi_value I18nAddon::GetTimePeriodName(napi_env env, napi_callback_info info) 218{ 219 napi_value result; 220 int32_t hour; 221 std::string localeTag; 222 if (GetParamOfGetTimePeriodName(env, info, localeTag, hour) == -1) { 223 HILOG_ERROR_I18N("GetTimePeriodName param error"); 224 napi_create_string_utf8(env, "", NAPI_AUTO_LENGTH, &result); 225 return result; 226 } 227 228 UErrorCode icuStatus = U_ZERO_ERROR; 229 icu::Locale locale = icu::Locale::forLanguageTag(localeTag.data(), icuStatus); 230 if (U_FAILURE(icuStatus) || !IsValidLocaleTag(locale)) { 231 ErrorUtil::NapiThrow(env, I18N_NOT_VALID, "locale", "a valid locale", true); 232 return nullptr; 233 } 234 icu::SimpleDateFormat* formatter = dynamic_cast<icu::SimpleDateFormat*> 235 (icu::DateFormat::createDateInstance(icu::DateFormat::EStyle::kDefault, locale)); 236 if (!formatter) { 237 HILOG_ERROR_I18N("GetTimePeriodName Failed to create SimpleDateFormat"); 238 napi_create_string_utf8(env, "", NAPI_AUTO_LENGTH, &result); 239 return result; 240 } 241 formatter->applyPattern("B"); 242 243 std::string temp; 244 icu::UnicodeString name; 245 icu::Calendar *calendar = icu::Calendar::createInstance(locale, icuStatus); 246 calendar->set(UCalendarDateFields::UCAL_HOUR_OF_DAY, hour); 247 formatter->format(calendar->getTime(icuStatus), name); 248 name.toUTF8String(temp); 249 napi_create_string_utf8(env, PseudoLocalizationProcessor(temp).c_str(), NAPI_AUTO_LENGTH, &result); 250 delete formatter; 251 delete calendar; 252 return result; 253} 254 255int I18nAddon::GetParamOfGetTimePeriodName(napi_env env, napi_callback_info info, std::string &tag, int32_t &hour) 256{ 257 size_t argc = 2; 258 napi_value argv[2] = { 0 }; 259 napi_value thisVar = nullptr; 260 void *data = nullptr; 261 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 262 if (status != napi_ok) { 263 HILOG_ERROR_I18N("GetTimePeriodName can't get parameters from getTimePerioudName."); 264 return -1; 265 } else if (argc < 1) { 266 ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, "hour", "", true); 267 return -1; 268 } 269 270 napi_valuetype valueType = napi_valuetype::napi_undefined; 271 napi_typeof(env, argv[0], &valueType); 272 if (valueType != napi_valuetype::napi_number) { 273 ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, "hour", "number", true); 274 return -1; 275 } 276 status = napi_get_value_int32(env, argv[0], &hour); 277 if (status != napi_ok) { 278 HILOG_ERROR_I18N("GetTimePeriodName can't get number from js param"); 279 return -1; 280 } 281 282 valueType = napi_valuetype::napi_undefined; 283 napi_typeof(env, argv[1], &valueType); 284 if (valueType == napi_valuetype::napi_null || valueType == napi_valuetype::napi_undefined) { 285 tag = LocaleConfig::GetSystemLocale(); 286 } else if (valueType == napi_valuetype::napi_string) { 287 int code = 0; 288 tag = VariableConvertor::GetString(env, argv[1], code); 289 if (code) { 290 HILOG_ERROR_I18N("GetTimePeriodName can't get string from js param"); 291 return -1; 292 } 293 } else { 294 ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, "locale", "string", true); 295 return -1; 296 } 297 return 0; 298} 299 300LocaleInfo* ProcessJsParamLocale(napi_env env, napi_value argv) 301{ 302 int32_t code = 0; 303 std::string localeTag = VariableConvertor::GetString(env, argv, code); 304 if (code != 0) { 305 HILOG_ERROR_I18N("ProcessJsParamLocale: Failed to obtain the parameter."); 306 return nullptr; 307 } 308 UErrorCode icuStatus = U_ZERO_ERROR; 309 icu::Locale locale = icu::Locale::forLanguageTag(localeTag.data(), icuStatus); 310 if (U_FAILURE(icuStatus) || !IsValidLocaleTag(locale)) { 311 ErrorUtil::NapiThrow(env, I18N_NOT_VALID, "locale", "a valid locale", true); 312 return nullptr; 313 } 314 return new LocaleInfo(localeTag); 315} 316 317bool ProcessJsParamLocaleList(napi_env env, napi_value argv, std::vector<LocaleInfo*> &candidateLocales, 318 LocaleInfo *requestLocale) 319{ 320 std::vector<std::string> localeTagList; 321 if (!VariableConvertor::GetStringArrayFromJsParam(env, argv, "localeList", localeTagList)) { 322 HILOG_ERROR_I18N("ProcessJsParamLocaleList: Failed to obtain the parameter."); 323 return false; 324 } 325 if (localeTagList.size() == 0) { 326 return true; 327 } 328 for (auto it = localeTagList.begin(); it != localeTagList.end(); ++it) { 329 UErrorCode icuStatus = U_ZERO_ERROR; 330 icu::Locale locale = icu::Locale::forLanguageTag(it->data(), icuStatus); 331 if (U_FAILURE(icuStatus) || !IsValidLocaleTag(locale)) { 332 HILOG_ERROR_I18N("GetBestMatchLocale param localeList Invalid: %{public}s.", it->data()); 333 ErrorUtil::NapiThrow(env, I18N_NOT_VALID, "locale of localeList", "a valid locale", true); 334 return false; 335 } 336 LocaleInfo *temp = new LocaleInfo(*it); 337 if (LocaleMatcher::Match(requestLocale, temp)) { 338 candidateLocales.push_back(temp); 339 } else { 340 delete temp; 341 } 342 } 343 return true; 344} 345 346void ReleaseParam(LocaleInfo *locale, std::vector<LocaleInfo*> &candidateLocales) 347{ 348 delete locale; 349 for (auto it = candidateLocales.begin(); it != candidateLocales.end(); ++it) { 350 delete *it; 351 } 352} 353 354napi_value I18nAddon::GetBestMatchLocale(napi_env env, napi_callback_info info) 355{ 356 size_t argc = 2; 357 napi_value argv[2] = { nullptr }; 358 napi_value thisVar = nullptr; 359 void *data = nullptr; 360 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 361 if (status != napi_ok || argc < 2) { // 2 is the request param num. 362 ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, "locale or localeList", "", true); 363 return nullptr; 364 } 365 LocaleInfo *requestLocale = ProcessJsParamLocale(env, argv[0]); 366 if (requestLocale == nullptr) { 367 return nullptr; 368 } 369 std::vector<LocaleInfo*> candidateLocales; 370 bool isValidParam = ProcessJsParamLocaleList(env, argv[1], candidateLocales, requestLocale); 371 if (!isValidParam) { 372 ReleaseParam(requestLocale, candidateLocales); 373 return nullptr; 374 } 375 std::string bestMatchLocaleTag = ""; 376 if (candidateLocales.size() > 0) { 377 LocaleInfo *bestMatch = candidateLocales[0]; 378 for (size_t i = 1; i < candidateLocales.size(); ++i) { 379 if (LocaleMatcher::IsMoreSuitable(bestMatch, candidateLocales[i], requestLocale) < 0) { 380 bestMatch = candidateLocales[i]; 381 } 382 } 383 bestMatchLocaleTag = bestMatch->ToString(); 384 } 385 ReleaseParam(requestLocale, candidateLocales); 386 napi_value result = nullptr; 387 status = napi_create_string_utf8(env, bestMatchLocaleTag.c_str(), NAPI_AUTO_LENGTH, &result); 388 if (status != napi_ok) { 389 HILOG_ERROR_I18N("Create format stirng failed."); 390 return nullptr; 391 } 392 return result; 393} 394 395napi_value I18nAddon::GetThreeLetterLanguage(napi_env env, napi_callback_info info) 396{ 397 size_t argc = 1; 398 napi_value argv[1] = { 0 }; 399 napi_value thisVar = nullptr; 400 void *data = nullptr; 401 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 402 if (status != napi_ok) { 403 HILOG_ERROR_I18N("GetThreeLetterLanguage napi get param error."); 404 return nullptr; 405 } else if (argc < 1) { 406 ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, "locale", "", true); 407 return nullptr; 408 } 409 410 napi_valuetype valueType = napi_valuetype::napi_undefined; 411 napi_typeof(env, argv[0], &valueType); 412 if (valueType != napi_valuetype::napi_string) { 413 ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, "locale", "string", true); 414 return nullptr; 415 } 416 417 int32_t code = 0; 418 std::string languageTag = VariableConvertor::GetString(env, argv[0], code); 419 if (code != 0) { 420 HILOG_ERROR_I18N("GetThreeLetterLanguage: Failed to obtain the parameter."); 421 return nullptr; 422 } 423 424 std::string language = GetISO3Language(languageTag); 425 426 napi_value result; 427 status = napi_create_string_utf8(env, language.c_str(), NAPI_AUTO_LENGTH, &result); 428 if (status != napi_ok || language == "") { 429 HILOG_ERROR_I18N("GetThreeLetterLanguage create string fail or empty"); 430 ErrorUtil::NapiThrow(env, I18N_NOT_VALID, "locale", "a valid locale", true); 431 return nullptr; 432 } 433 return result; 434} 435 436napi_value I18nAddon::GetThreeLetterRegion(napi_env env, napi_callback_info info) 437{ 438 size_t argc = 1; 439 napi_value argv[1] = { 0 }; 440 napi_value thisVar = nullptr; 441 void *data = nullptr; 442 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 443 if (status != napi_ok) { 444 HILOG_ERROR_I18N("GetThreeLetterRegion: Failed to obtain the parameter."); 445 return nullptr; 446 } else if (argc < 1) { 447 ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, "locale", "", true); 448 return nullptr; 449 } 450 451 napi_valuetype valueType = napi_valuetype::napi_undefined; 452 napi_typeof(env, argv[0], &valueType); 453 if (valueType != napi_valuetype::napi_string) { 454 ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, "locale", "string", true); 455 return nullptr; 456 } 457 458 int32_t code = 0; 459 std::string regionTag = VariableConvertor::GetString(env, argv[0], code); 460 if (code != 0) { 461 HILOG_ERROR_I18N("GetThreeLetterRegion: Failed to obtain the parameter."); 462 return nullptr; 463 } 464 465 std::string country = GetISO3Country(regionTag); 466 467 napi_value result; 468 status = napi_create_string_utf8(env, country.c_str(), NAPI_AUTO_LENGTH, &result); 469 if (status != napi_ok || country == "") { 470 HILOG_ERROR_I18N("GetThreeLetterRegion create string fail or empty"); 471 ErrorUtil::NapiThrow(env, I18N_NOT_VALID, "locale", "a valid locale", true); 472 return nullptr; 473 } 474 return result; 475} 476 477napi_value I18nAddon::InitI18nTransliterator(napi_env env, napi_value exports) 478{ 479 napi_property_descriptor properties[] = { 480 DECLARE_NAPI_FUNCTION("transform", Transform), 481 }; 482 napi_value constructor = nullptr; 483 napi_status status = napi_define_class(env, "Transliterator", NAPI_AUTO_LENGTH, I18nTransliteratorConstructor, 484 nullptr, sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor); 485 if (status != napi_ok) { 486 HILOG_ERROR_I18N("InitI18nTransliterator: Failed to define transliterator class at Init"); 487 return nullptr; 488 } 489 exports = I18nAddon::InitTransliterator(env, exports); 490 g_transConstructor = new (std::nothrow) napi_ref; 491 if (!g_transConstructor) { 492 HILOG_ERROR_I18N("InitI18nTransliterator: Failed to create trans ref at init"); 493 return nullptr; 494 } 495 status = napi_create_reference(env, constructor, 1, g_transConstructor); 496 if (status != napi_ok) { 497 HILOG_ERROR_I18N("InitI18nTransliterator: Failed to create trans reference at init"); 498 return nullptr; 499 } 500 return exports; 501} 502 503napi_value I18nAddon::InitTransliterator(napi_env env, napi_value exports) 504{ 505 napi_property_descriptor properties[] = { 506 DECLARE_NAPI_STATIC_FUNCTION("getAvailableIDs", GetAvailableIDs), 507 DECLARE_NAPI_STATIC_FUNCTION("getInstance", GetTransliteratorInstance) 508 }; 509 napi_value constructor = nullptr; 510 napi_status status = napi_define_class(env, "I18nTransliterator", NAPI_AUTO_LENGTH, JSUtils::DefaultConstructor, 511 nullptr, sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor); 512 if (status != napi_ok) { 513 HILOG_ERROR_I18N("InitTransliterator: Failed to define class Transliterator."); 514 return nullptr; 515 } 516 status = napi_set_named_property(env, exports, "Transliterator", constructor); 517 if (status != napi_ok) { 518 HILOG_ERROR_I18N("InitTransliterator: Set property failed When InitTransliterator."); 519 return nullptr; 520 } 521 return exports; 522} 523 524napi_value I18nAddon::I18nTransliteratorConstructor(napi_env env, napi_callback_info info) 525{ 526 size_t argc = 1; 527 napi_value argv[1] = { 0 }; 528 napi_value thisVar = nullptr; 529 void *data = nullptr; 530 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 531 if (status != napi_ok) { 532 return nullptr; 533 } 534 napi_valuetype valueType = napi_valuetype::napi_undefined; 535 napi_typeof(env, argv[0], &valueType); 536 if (valueType != napi_valuetype::napi_string) { 537 HILOG_ERROR_I18N("I18nTransliteratorConstructor: Parameter type does not match"); 538 return nullptr; 539 } 540 int32_t code = 0; 541 std::string idTag = VariableConvertor::GetString(env, argv[0], code); 542 if (code) { 543 return nullptr; 544 } 545 std::unique_ptr<I18nAddon> obj = nullptr; 546 obj = std::make_unique<I18nAddon>(); 547 status = 548 napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()), I18nAddon::Destructor, nullptr, nullptr); 549 if (status != napi_ok) { 550 HILOG_ERROR_I18N("I18nTransliteratorConstructor: TransliteratorConstructor: Wrap II18nAddon failed"); 551 return nullptr; 552 } 553 if (!obj->InitTransliteratorContext(env, info, idTag)) { 554 obj.release(); 555 return nullptr; 556 } 557 obj.release(); 558 return thisVar; 559} 560 561bool I18nAddon::InitTransliteratorContext(napi_env env, napi_callback_info info, const std::string &idTag) 562{ 563 UErrorCode status = U_ZERO_ERROR; 564 icu::UnicodeString unistr = icu::UnicodeString::fromUTF8(idTag); 565 icu::Transliterator *trans = icu::Transliterator::createInstance(unistr, UTransDirection::UTRANS_FORWARD, status); 566 if (U_FAILURE(status) || (trans == nullptr)) { 567 return false; 568 } 569 transliterator_ = std::unique_ptr<icu::Transliterator>(trans); 570 return transliterator_ != nullptr; 571} 572 573napi_value I18nAddon::Transform(napi_env env, napi_callback_info info) 574{ 575 size_t argc = 1; 576 napi_value argv[1] = { nullptr }; 577 napi_value thisVar = nullptr; 578 void *data = nullptr; 579 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 580 I18nAddon *obj = nullptr; 581 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj)); 582 if (status != napi_ok || !obj || !obj->transliterator_) { 583 HILOG_ERROR_I18N("Get Transliterator object failed"); 584 return nullptr; 585 } 586 if (!argv[0]) { 587 return nullptr; 588 } 589 napi_valuetype valueType = napi_valuetype::napi_undefined; 590 napi_typeof(env, argv[0], &valueType); 591 if (valueType != napi_valuetype::napi_string) { 592 HILOG_ERROR_I18N("Transform: Parameter type does not match"); 593 return nullptr; 594 } 595 size_t len = 0; 596 status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len); 597 if (status != napi_ok) { 598 HILOG_ERROR_I18N("Transform: Get field length failed napi_get_value_string_utf8"); 599 return nullptr; 600 } 601 std::vector<char> buf(len + 1); 602 status = napi_get_value_string_utf8(env, argv[0], buf.data(), len + 1, &len); 603 if (status != napi_ok) { 604 HILOG_ERROR_I18N("Transform: Get string value failed"); 605 return nullptr; 606 } 607 icu::UnicodeString unistr = icu::UnicodeString::fromUTF8(buf.data()); 608 obj->transliterator_->transliterate(unistr); 609 std::string temp; 610 unistr.toUTF8String(temp); 611 napi_value value; 612 status = napi_create_string_utf8(env, temp.c_str(), NAPI_AUTO_LENGTH, &value); 613 if (status != napi_ok) { 614 HILOG_ERROR_I18N("Transform: Get field length failed napi_create_string_utf8"); 615 return nullptr; 616 } 617 return value; 618} 619 620napi_value I18nAddon::GetAvailableIDs(napi_env env, napi_callback_info info) 621{ 622 size_t argc = 0; 623 napi_value *argv = nullptr; 624 napi_value thisVar = nullptr; 625 void *data = nullptr; 626 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 627 if (status != napi_ok) { 628 return nullptr; 629 } 630 UErrorCode icuStatus = U_ZERO_ERROR; 631 icu::StringEnumeration *strenum = icu::Transliterator::getAvailableIDs(icuStatus); 632 if (U_FAILURE(icuStatus)) { 633 HILOG_ERROR_I18N("Failed to get available ids"); 634 if (strenum) { 635 delete strenum; 636 } 637 return nullptr; 638 } 639 640 napi_value result = nullptr; 641 napi_create_array(env, &result); 642 uint32_t i = 0; 643 const char *temp = nullptr; 644 if (strenum == nullptr) { 645 return nullptr; 646 } 647 while ((temp = strenum->next(nullptr, icuStatus)) != nullptr) { 648 if (U_FAILURE(icuStatus)) { 649 break; 650 } 651 napi_value val = nullptr; 652 napi_create_string_utf8(env, temp, strlen(temp), &val); 653 napi_set_element(env, result, i, val); 654 ++i; 655 } 656 delete strenum; 657 return result; 658} 659 660napi_value I18nAddon::GetTransliteratorInstance(napi_env env, napi_callback_info info) 661{ 662 size_t argc = 1; // retrieve 2 arguments 663 napi_value argv[1] = { 0 }; 664 napi_value thisVar = nullptr; 665 void *data = nullptr; 666 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 667 napi_value constructor = nullptr; 668 napi_status status = napi_get_reference_value(env, *g_transConstructor, &constructor); 669 if (status != napi_ok) { 670 HILOG_ERROR_I18N("Failed to create reference at GetCalendar"); 671 return nullptr; 672 } 673 napi_value result = nullptr; 674 status = napi_new_instance(env, constructor, 1, argv, &result); // 2 arguments 675 if (status != napi_ok) { 676 HILOG_ERROR_I18N("Get Transliterator create instance failed"); 677 return nullptr; 678 } 679 return result; 680} 681 682napi_value I18nAddon::IsRTL(napi_env env, napi_callback_info info) 683{ 684 size_t argc = 1; 685 napi_value argv[1] = { 0 }; 686 napi_value thisVar = nullptr; 687 void *data = nullptr; 688 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 689 if (status != napi_ok) { 690 return nullptr; 691 } 692 size_t len = 0; 693 napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len); 694 std::vector<char> localeBuf(len + 1); 695 status = napi_get_value_string_utf8(env, argv[0], localeBuf.data(), len + 1, &len); 696 if (status != napi_ok) { 697 HILOG_ERROR_I18N("IsRTL: Failed to get string item"); 698 return nullptr; 699 } 700 bool isRTL = LocaleConfig::IsRTL(localeBuf.data()); 701 napi_value result = nullptr; 702 status = napi_get_boolean(env, isRTL, &result); 703 if (status != napi_ok) { 704 HILOG_ERROR_I18N("IsRTL failed"); 705 return nullptr; 706 } 707 return result; 708} 709 710napi_value I18nAddon::InitPhoneNumberFormat(napi_env env, napi_value exports) 711{ 712 napi_status status = napi_ok; 713 napi_property_descriptor properties[] = { 714 DECLARE_NAPI_FUNCTION("isValidNumber", IsValidPhoneNumber), 715 DECLARE_NAPI_FUNCTION("format", FormatPhoneNumber), 716 DECLARE_NAPI_FUNCTION("getLocationName", GetLocationName) 717 }; 718 719 napi_value constructor; 720 status = napi_define_class(env, "PhoneNumberFormat", NAPI_AUTO_LENGTH, PhoneNumberFormatConstructor, nullptr, 721 sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor); 722 if (status != napi_ok) { 723 HILOG_ERROR_I18N("InitPhoneNumberFormat: Define class failed when InitPhoneNumberFormat"); 724 return nullptr; 725 } 726 727 status = napi_set_named_property(env, exports, "PhoneNumberFormat", constructor); 728 if (status != napi_ok) { 729 HILOG_ERROR_I18N("Set property failed when InitPhoneNumberFormat"); 730 return nullptr; 731 } 732 return exports; 733} 734 735napi_value I18nAddon::PhoneNumberFormatConstructor(napi_env env, napi_callback_info info) 736{ 737 size_t argc = 2; 738 napi_value argv[2] = { 0 }; 739 napi_value thisVar = nullptr; 740 void *data = nullptr; 741 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 742 if (status != napi_ok) { 743 return nullptr; 744 } 745 napi_valuetype valueType = napi_valuetype::napi_undefined; 746 napi_typeof(env, argv[0], &valueType); 747 if (valueType != napi_valuetype::napi_string) { 748 HILOG_ERROR_I18N("PhoneNumberFormatConstructor: Parameter type does not match"); 749 return nullptr; 750 } 751 size_t len = 0; 752 status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len); 753 if (status != napi_ok) { 754 HILOG_ERROR_I18N("PhoneNumberFormatConstructor: Get country tag length failed"); 755 return nullptr; 756 } 757 std::vector<char> country (len + 1); 758 status = napi_get_value_string_utf8(env, argv[0], country.data(), len + 1, &len); 759 if (status != napi_ok) { 760 HILOG_ERROR_I18N("Get country tag failed"); 761 return nullptr; 762 } 763 std::map<std::string, std::string> options; 764 std::string typeStr; 765 VariableConvertor::GetOptionValue(env, argv[1], "type", typeStr); 766 options.insert(std::make_pair("type", typeStr)); 767 std::unique_ptr<I18nAddon> obj = nullptr; 768 obj = std::make_unique<I18nAddon>(); 769 status = napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()), 770 I18nAddon::Destructor, nullptr, nullptr); 771 if (status != napi_ok) { 772 HILOG_ERROR_I18N("PhoneNumberFormatConstructor: Wrap I18nAddon failed"); 773 return nullptr; 774 } 775 if (!obj->InitPhoneNumberFormatContext(env, info, country.data(), options)) { 776 return nullptr; 777 } 778 obj.release(); 779 return thisVar; 780} 781 782bool I18nAddon::InitPhoneNumberFormatContext(napi_env env, napi_callback_info info, const std::string &country, 783 const std::map<std::string, std::string> &options) 784{ 785 napi_value global = nullptr; 786 napi_status status = napi_get_global(env, &global); 787 if (status != napi_ok) { 788 HILOG_ERROR_I18N("InitPhoneNumberFormatContext: Get global failed"); 789 return false; 790 } 791 env_ = env; 792 phonenumberfmt_ = PhoneNumberFormat::CreateInstance(country, options); 793 794 return phonenumberfmt_ != nullptr; 795} 796 797napi_value I18nAddon::IsValidPhoneNumber(napi_env env, napi_callback_info info) 798{ 799 size_t argc = 1; 800 napi_value argv[1] = { 0 }; 801 napi_value thisVar = nullptr; 802 void *data = nullptr; 803 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 804 napi_valuetype valueType = napi_valuetype::napi_undefined; 805 napi_typeof(env, argv[0], &valueType); 806 if (valueType != napi_valuetype::napi_string) { 807 HILOG_ERROR_I18N("IsValidPhoneNumber: Parameter type does not match"); 808 return nullptr; 809 } 810 811 size_t len = 0; 812 napi_status status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len); 813 if (status != napi_ok) { 814 HILOG_ERROR_I18N("IsValidPhoneNumber: Get phone number length failed"); 815 return nullptr; 816 } 817 std::vector<char> buf(len + 1); 818 status = napi_get_value_string_utf8(env, argv[0], buf.data(), len + 1, &len); 819 if (status != napi_ok) { 820 HILOG_ERROR_I18N("IsValidPhoneNumber: Get phone number failed"); 821 return nullptr; 822 } 823 824 I18nAddon *obj = nullptr; 825 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj)); 826 if (status != napi_ok || !obj || !obj->phonenumberfmt_) { 827 HILOG_ERROR_I18N("IsValidPhoneNumber: GetPhoneNumberFormat object failed"); 828 return nullptr; 829 } 830 831 bool isValid = obj->phonenumberfmt_->isValidPhoneNumber(buf.data()); 832 833 napi_value result = nullptr; 834 status = napi_get_boolean(env, isValid, &result); 835 if (status != napi_ok) { 836 HILOG_ERROR_I18N("IsValidPhoneNumber: Create boolean failed"); 837 return nullptr; 838 } 839 840 return result; 841} 842 843napi_value I18nAddon::GetLocationName(napi_env env, napi_callback_info info) 844{ 845 size_t argc = 2; 846 napi_value argv[2] = {0, 0}; 847 napi_value thisVar = nullptr; 848 void *data = nullptr; 849 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 850 851 int32_t code = 0; 852 std::string number = VariableConvertor::GetString(env, argv[0], code); 853 if (code) { 854 return nullptr; 855 } 856 std::string language = VariableConvertor::GetString(env, argv[1], code); 857 if (code) { 858 return nullptr; 859 } 860 861 I18nAddon *obj = nullptr; 862 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj)); 863 if (status != napi_ok || !obj || !obj->phonenumberfmt_) { 864 HILOG_ERROR_I18N("GetLocationName: GetPhoneNumberFormat object failed"); 865 return nullptr; 866 } 867 868 std::string resStr = obj->phonenumberfmt_->getLocationName(number.data(), language.data()); 869 napi_value result = nullptr; 870 status = napi_create_string_utf8(env, resStr.c_str(), NAPI_AUTO_LENGTH, &result); 871 if (status != napi_ok) { 872 HILOG_ERROR_I18N("Create result string failed"); 873 return nullptr; 874 } 875 876 return result; 877} 878 879napi_value I18nAddon::FormatPhoneNumber(napi_env env, napi_callback_info info) 880{ 881 size_t argc = 1; 882 napi_value argv[1] = { 0 }; 883 napi_value thisVar = nullptr; 884 void *data = nullptr; 885 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 886 napi_valuetype valueType = napi_valuetype::napi_undefined; 887 napi_typeof(env, argv[0], &valueType); 888 if (valueType != napi_valuetype::napi_string) { 889 HILOG_ERROR_I18N("FormatPhoneNumber: Parameter type does not match"); 890 return nullptr; 891 } 892 893 size_t len = 0; 894 napi_status status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len); 895 if (status != napi_ok) { 896 HILOG_ERROR_I18N("FormatPhoneNumber: Get phone number length failed"); 897 return nullptr; 898 } 899 std::vector<char> buf(len + 1); 900 status = napi_get_value_string_utf8(env, argv[0], buf.data(), len + 1, &len); 901 if (status != napi_ok) { 902 HILOG_ERROR_I18N("FormatPhoneNumber: Get phone number failed"); 903 return nullptr; 904 } 905 906 I18nAddon *obj = nullptr; 907 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj)); 908 if (status != napi_ok || !obj || !obj->phonenumberfmt_) { 909 HILOG_ERROR_I18N("Get PhoneNumberFormat object failed"); 910 return nullptr; 911 } 912 913 std::string formattedPhoneNumber = obj->phonenumberfmt_->format(buf.data()); 914 915 napi_value result = nullptr; 916 status = napi_create_string_utf8(env, formattedPhoneNumber.c_str(), NAPI_AUTO_LENGTH, &result); 917 if (status != napi_ok) { 918 HILOG_ERROR_I18N("Create format phone number failed"); 919 return nullptr; 920 } 921 return result; 922} 923 924napi_value I18nAddon::InitI18nIndexUtil(napi_env env, napi_value exports) 925{ 926 napi_property_descriptor properties[] = { 927 DECLARE_NAPI_FUNCTION("getIndexList", GetIndexList), 928 DECLARE_NAPI_FUNCTION("addLocale", AddLocale), 929 DECLARE_NAPI_FUNCTION("getIndex", GetIndex) 930 }; 931 932 napi_value constructor = nullptr; 933 napi_status status = napi_define_class(env, "IndexUtil", NAPI_AUTO_LENGTH, I18nIndexUtilConstructor, nullptr, 934 sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor); 935 if (status != napi_ok) { 936 HILOG_ERROR_I18N("InitI18nIndexUtil: Define class failed when InitI18nIndexUtil."); 937 return nullptr; 938 } 939 exports = I18nAddon::InitIndexUtil(env, exports); 940 status = napi_create_reference(env, constructor, 1, &g_indexUtilConstructor); 941 if (status != napi_ok) { 942 HILOG_ERROR_I18N("InitI18nIndexUtil: Failed to create reference at init."); 943 return nullptr; 944 } 945 return exports; 946} 947 948napi_value I18nAddon::InitIndexUtil(napi_env env, napi_value exports) 949{ 950 napi_property_descriptor properties[] = {}; 951 napi_value constructor = nullptr; 952 napi_status status = napi_define_class(env, "I18nIndexUtil", NAPI_AUTO_LENGTH, JSUtils::DefaultConstructor, 953 nullptr, sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor); 954 if (status != napi_ok) { 955 HILOG_ERROR_I18N("InitIndexUtil: Failed to define class IndexUtil."); 956 return nullptr; 957 } 958 status = napi_set_named_property(env, exports, "IndexUtil", constructor); 959 if (status != napi_ok) { 960 HILOG_ERROR_I18N("InitIndexUtil: Set property failed When InitIndexUtil."); 961 return nullptr; 962 } 963 return exports; 964} 965 966napi_value I18nAddon::I18nBreakIteratorConstructor(napi_env env, napi_callback_info info) 967{ 968 size_t argc = 1; 969 napi_value argv[1] = { nullptr }; 970 napi_value thisVar = nullptr; 971 void *data = nullptr; 972 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 973 if (status != napi_ok) { 974 return nullptr; 975 } 976 napi_valuetype valueType = napi_valuetype::napi_undefined; 977 napi_typeof(env, argv[0], &valueType); 978 if (valueType != napi_valuetype::napi_string) { 979 HILOG_ERROR_I18N("BreakIteratorConstructor: Parameter type does not match"); 980 return nullptr; 981 } 982 int32_t code = 0; 983 std::string localeTag = VariableConvertor::GetString(env, argv[0], code); 984 if (code) { 985 return nullptr; 986 } 987 std::unique_ptr<I18nAddon> obj = nullptr; 988 obj = std::make_unique<I18nAddon>(); 989 status = 990 napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()), I18nAddon::Destructor, nullptr, nullptr); 991 if (status != napi_ok) { 992 HILOG_ERROR_I18N("BreakIteratorConstructor: Wrap II18nAddon failed"); 993 return nullptr; 994 } 995 obj->brkiter_ = std::make_unique<I18nBreakIterator>(localeTag); 996 if (!obj->brkiter_) { 997 HILOG_ERROR_I18N("Wrap BreakIterator failed"); 998 return nullptr; 999 } 1000 obj.release(); 1001 return thisVar; 1002} 1003 1004napi_value I18nAddon::InitI18nBreakIterator(napi_env env, napi_value exports) 1005{ 1006 napi_property_descriptor properties[] = { 1007 DECLARE_NAPI_FUNCTION("current", Current), 1008 DECLARE_NAPI_FUNCTION("first", First), 1009 DECLARE_NAPI_FUNCTION("last", Last), 1010 DECLARE_NAPI_FUNCTION("next", Next), 1011 DECLARE_NAPI_FUNCTION("previous", Previous), 1012 DECLARE_NAPI_FUNCTION("setLineBreakText", SetText), 1013 DECLARE_NAPI_FUNCTION("following", Following), 1014 DECLARE_NAPI_FUNCTION("getLineBreakText", GetText), 1015 DECLARE_NAPI_FUNCTION("isBoundary", IsBoundary) 1016 }; 1017 napi_value constructor = nullptr; 1018 napi_status status = napi_define_class(env, "BreakIterator", NAPI_AUTO_LENGTH, I18nBreakIteratorConstructor, 1019 nullptr, sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor); 1020 if (status != napi_ok) { 1021 HILOG_ERROR_I18N("InitI18nBreakIterator: Failed to define class BreakIterator at Init"); 1022 return nullptr; 1023 } 1024 exports = I18nAddon::InitBreakIterator(env, exports); 1025 g_brkConstructor = new (std::nothrow) napi_ref; 1026 if (!g_brkConstructor) { 1027 HILOG_ERROR_I18N("InitI18nBreakIterator: Failed to create brkiterator ref at init"); 1028 return nullptr; 1029 } 1030 status = napi_create_reference(env, constructor, 1, g_brkConstructor); 1031 if (status != napi_ok) { 1032 HILOG_ERROR_I18N("InitI18nBreakIterator: Failed to create reference g_brkConstructor at init"); 1033 return nullptr; 1034 } 1035 return exports; 1036} 1037 1038napi_value I18nAddon::InitBreakIterator(napi_env env, napi_value exports) 1039{ 1040 napi_property_descriptor properties[] = {}; 1041 napi_value constructor = nullptr; 1042 napi_status status = napi_define_class(env, "I18nBreakIterator", NAPI_AUTO_LENGTH, JSUtils::DefaultConstructor, 1043 nullptr, sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor); 1044 if (status != napi_ok) { 1045 HILOG_ERROR_I18N("InitBreakIterator: Failed to define class BreakIterator."); 1046 return nullptr; 1047 } 1048 status = napi_set_named_property(env, exports, "BreakIterator", constructor); 1049 if (status != napi_ok) { 1050 HILOG_ERROR_I18N("InitBreakIterator: Set property failed When InitBreakIterator."); 1051 return nullptr; 1052 } 1053 return exports; 1054} 1055 1056napi_value I18nAddon::GetLineInstance(napi_env env, napi_callback_info info) 1057{ 1058 size_t argc = 1; 1059 napi_value argv[1] = { nullptr }; 1060 napi_value thisVar = nullptr; 1061 void *data = nullptr; 1062 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 1063 napi_value constructor = nullptr; 1064 napi_status status = napi_get_reference_value(env, *g_brkConstructor, &constructor); 1065 if (status != napi_ok) { 1066 HILOG_ERROR_I18N("Failed to create reference at GetLineInstance"); 1067 return nullptr; 1068 } 1069 if (!argv[0]) { 1070 return nullptr; 1071 } 1072 napi_value result = nullptr; 1073 status = napi_new_instance(env, constructor, 1, argv, &result); // 1 arguments 1074 if (status != napi_ok) { 1075 HILOG_ERROR_I18N("GetLineInstance create instance failed"); 1076 return nullptr; 1077 } 1078 return result; 1079} 1080 1081napi_value I18nAddon::Current(napi_env env, napi_callback_info info) 1082{ 1083 size_t argc = 0; 1084 napi_value *argv = nullptr; 1085 napi_value thisVar = nullptr; 1086 void *data = nullptr; 1087 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 1088 I18nAddon *obj = nullptr; 1089 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj)); 1090 if (status != napi_ok || !obj || !obj->brkiter_) { 1091 HILOG_ERROR_I18N("Current: Get BreakIterator object failed"); 1092 return nullptr; 1093 } 1094 int value = obj->brkiter_->Current(); 1095 napi_value result = nullptr; 1096 status = napi_create_int32(env, value, &result); 1097 if (status != napi_ok) { 1098 HILOG_ERROR_I18N("Current: Create int32_t value failed"); 1099 return nullptr; 1100 } 1101 return result; 1102} 1103 1104napi_value I18nAddon::First(napi_env env, napi_callback_info info) 1105{ 1106 size_t argc = 0; 1107 napi_value *argv = nullptr; 1108 napi_value thisVar = nullptr; 1109 void *data = nullptr; 1110 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 1111 I18nAddon *obj = nullptr; 1112 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj)); 1113 if (status != napi_ok || !obj || !obj->brkiter_) { 1114 HILOG_ERROR_I18N("First: Get BreakIterator object failed"); 1115 return nullptr; 1116 } 1117 int value = obj->brkiter_->First(); 1118 napi_value result = nullptr; 1119 status = napi_create_int32(env, value, &result); 1120 if (status != napi_ok) { 1121 HILOG_ERROR_I18N("First: Create int32_t value failed"); 1122 return nullptr; 1123 } 1124 return result; 1125} 1126 1127napi_value I18nAddon::Last(napi_env env, napi_callback_info info) 1128{ 1129 size_t argc = 0; 1130 napi_value *argv = nullptr; 1131 napi_value thisVar = nullptr; 1132 void *data = nullptr; 1133 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 1134 I18nAddon *obj = nullptr; 1135 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj)); 1136 if (status != napi_ok || !obj || !obj->brkiter_) { 1137 HILOG_ERROR_I18N("Last: Get BreakIterator object failed"); 1138 return nullptr; 1139 } 1140 int value = obj->brkiter_->Last(); 1141 napi_value result = nullptr; 1142 status = napi_create_int32(env, value, &result); 1143 if (status != napi_ok) { 1144 HILOG_ERROR_I18N("Last: Create int32_t value failed"); 1145 return nullptr; 1146 } 1147 return result; 1148} 1149 1150napi_value I18nAddon::Previous(napi_env env, napi_callback_info info) 1151{ 1152 size_t argc = 0; 1153 napi_value *argv = nullptr; 1154 napi_value thisVar = nullptr; 1155 void *data = nullptr; 1156 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 1157 I18nAddon *obj = nullptr; 1158 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj)); 1159 if (status != napi_ok || !obj || !obj->brkiter_) { 1160 HILOG_ERROR_I18N("Previous: Get BreakIterator object failed"); 1161 return nullptr; 1162 } 1163 int value = obj->brkiter_->Previous(); 1164 napi_value result = nullptr; 1165 status = napi_create_int32(env, value, &result); 1166 if (status != napi_ok) { 1167 HILOG_ERROR_I18N("Previous: Create int32_t value failed"); 1168 return nullptr; 1169 } 1170 return result; 1171} 1172 1173napi_value I18nAddon::Next(napi_env env, napi_callback_info info) 1174{ 1175 size_t argc = 1; 1176 napi_value argv[1] = { nullptr }; 1177 napi_value thisVar = nullptr; 1178 void *data = nullptr; 1179 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 1180 I18nAddon *obj = nullptr; 1181 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj)); 1182 if (status != napi_ok || !obj || !obj->brkiter_) { 1183 HILOG_ERROR_I18N("Next: Get BreakIterator object failed"); 1184 return nullptr; 1185 } 1186 int value = 1; 1187 if (VariableConvertor::CheckNapiValueType(env, argv[0])) { 1188 napi_valuetype valueType = napi_valuetype::napi_undefined; 1189 napi_typeof(env, argv[0], &valueType); 1190 if (valueType != napi_valuetype::napi_number) { 1191 HILOG_ERROR_I18N("Next: Parameter type does not match"); 1192 return nullptr; 1193 } 1194 status = napi_get_value_int32(env, argv[0], &value); 1195 if (status != napi_ok) { 1196 HILOG_ERROR_I18N("Next: Retrieve next value failed"); 1197 return nullptr; 1198 } 1199 } 1200 value = obj->brkiter_->Next(value); 1201 napi_value result = nullptr; 1202 status = napi_create_int32(env, value, &result); 1203 if (status != napi_ok) { 1204 HILOG_ERROR_I18N("Next: Create int32_t value failed"); 1205 return nullptr; 1206 } 1207 return result; 1208} 1209 1210napi_value I18nAddon::SetText(napi_env env, napi_callback_info info) 1211{ 1212 size_t argc = 1; 1213 napi_value argv[1] = { nullptr }; 1214 napi_value thisVar = nullptr; 1215 void *data = nullptr; 1216 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 1217 I18nAddon *obj = nullptr; 1218 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj)); 1219 if (status != napi_ok || !obj || !obj->brkiter_) { 1220 HILOG_ERROR_I18N("SetText: Get BreakIterator object failed"); 1221 return nullptr; 1222 } 1223 if (!argv[0]) { 1224 return nullptr; 1225 } 1226 napi_valuetype valueType = napi_valuetype::napi_undefined; 1227 napi_typeof(env, argv[0], &valueType); 1228 if (valueType != napi_valuetype::napi_string) { 1229 HILOG_ERROR_I18N("SetText: Parameter type does not match"); 1230 return nullptr; 1231 } 1232 size_t len = 0; 1233 status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len); 1234 if (status != napi_ok) { 1235 HILOG_ERROR_I18N("SetText: Get field length failed"); 1236 return nullptr; 1237 } 1238 std::vector<char> buf(len + 1); 1239 status = napi_get_value_string_utf8(env, argv[0], buf.data(), len + 1, &len); 1240 if (status != napi_ok) { 1241 HILOG_ERROR_I18N("SetText: Get string value failed"); 1242 return nullptr; 1243 } 1244 obj->brkiter_->SetText(buf.data()); 1245 return nullptr; 1246} 1247 1248napi_value I18nAddon::GetText(napi_env env, napi_callback_info info) 1249{ 1250 size_t argc = 0; 1251 napi_value *argv = nullptr; 1252 napi_value thisVar = nullptr; 1253 void *data = nullptr; 1254 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 1255 I18nAddon *obj = nullptr; 1256 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj)); 1257 if (status != napi_ok || !obj || !obj->brkiter_) { 1258 HILOG_ERROR_I18N("GetText: Get BreakIterator object failed"); 1259 return nullptr; 1260 } 1261 napi_value value = nullptr; 1262 std::string temp; 1263 obj->brkiter_->GetText(temp); 1264 status = napi_create_string_utf8(env, temp.c_str(), NAPI_AUTO_LENGTH, &value); 1265 if (status != napi_ok) { 1266 HILOG_ERROR_I18N("GetText: Get field length failed"); 1267 return nullptr; 1268 } 1269 return value; 1270} 1271 1272napi_value I18nAddon::Following(napi_env env, napi_callback_info info) 1273{ 1274 size_t argc = 1; 1275 napi_value argv[1] = { nullptr }; 1276 napi_value thisVar = nullptr; 1277 void *data = nullptr; 1278 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 1279 I18nAddon *obj = nullptr; 1280 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj)); 1281 if (status != napi_ok || !obj || !obj->brkiter_) { 1282 HILOG_ERROR_I18N("Following: Get BreakIterator object failed"); 1283 return nullptr; 1284 } 1285 if (!argv[0]) { 1286 return nullptr; 1287 } 1288 napi_valuetype valueType = napi_valuetype::napi_undefined; 1289 napi_typeof(env, argv[0], &valueType); 1290 if (valueType != napi_valuetype::napi_number) { 1291 HILOG_ERROR_I18N("Following: Parameter type does not match"); 1292 return nullptr; 1293 } 1294 int value; 1295 status = napi_get_value_int32(env, argv[0], &value); 1296 if (status != napi_ok) { 1297 HILOG_ERROR_I18N("Following: Retrieve following value failed"); 1298 return nullptr; 1299 } 1300 value = obj->brkiter_->Following(value); 1301 napi_value result = nullptr; 1302 status = napi_create_int32(env, value, &result); 1303 if (status != napi_ok) { 1304 HILOG_ERROR_I18N("Following: Create int32_t value failed"); 1305 return nullptr; 1306 } 1307 return result; 1308} 1309 1310napi_value I18nAddon::IsBoundary(napi_env env, napi_callback_info info) 1311{ 1312 size_t argc = 1; 1313 napi_value argv[1] = { nullptr }; 1314 napi_value thisVar = nullptr; 1315 void *data = nullptr; 1316 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 1317 I18nAddon *obj = nullptr; 1318 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj)); 1319 if (status != napi_ok || !obj || !obj->brkiter_) { 1320 HILOG_ERROR_I18N("IsBoundary: Get BreakIterator object failed"); 1321 return nullptr; 1322 } 1323 if (!argv[0]) { 1324 return nullptr; 1325 } 1326 napi_valuetype valueType = napi_valuetype::napi_undefined; 1327 int value; 1328 napi_typeof(env, argv[0], &valueType); 1329 if (valueType != napi_valuetype::napi_number) { 1330 HILOG_ERROR_I18N("IsBoundary: Parameter type does not match"); 1331 return nullptr; 1332 } 1333 status = napi_get_value_int32(env, argv[0], &value); 1334 if (status != napi_ok) { 1335 HILOG_ERROR_I18N("IsBoundary: Retrieve following value failed"); 1336 return nullptr; 1337 } 1338 bool boundary = obj->brkiter_->IsBoundary(value); 1339 napi_value result = nullptr; 1340 status = napi_get_boolean(env, boundary, &result); 1341 if (status != napi_ok) { 1342 HILOG_ERROR_I18N("IsBoundary: Create boolean failed"); 1343 return nullptr; 1344 } 1345 return result; 1346} 1347 1348napi_value I18nAddon::I18nIndexUtilConstructor(napi_env env, napi_callback_info info) 1349{ 1350 size_t argc = 1; 1351 napi_value argv[1] = { nullptr }; 1352 napi_value thisVar = nullptr; 1353 void *data = nullptr; 1354 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 1355 if (status != napi_ok) { 1356 return nullptr; 1357 } 1358 std::string localeTag = ""; 1359 if (argc > 0) { 1360 napi_valuetype valueType = napi_valuetype::napi_undefined; 1361 napi_typeof(env, argv[0], &valueType); 1362 if (valueType != napi_valuetype::napi_string) { 1363 HILOG_ERROR_I18N("IndexUtilConstructor: Parameter type does not match"); 1364 return nullptr; 1365 } 1366 size_t len = 0; 1367 status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len); 1368 if (status != napi_ok) { 1369 HILOG_ERROR_I18N("IndexUtilConstructor: Get locale length failed"); 1370 return nullptr; 1371 } 1372 std::vector<char> localeBuf(len + 1); 1373 status = napi_get_value_string_utf8(env, argv[0], localeBuf.data(), len + 1, &len); 1374 if (status != napi_ok) { 1375 HILOG_ERROR_I18N("IndexUtilConstructor: Get locale failed"); 1376 return nullptr; 1377 } 1378 localeTag = localeBuf.data(); 1379 } 1380 std::unique_ptr<I18nAddon> obj = nullptr; 1381 obj = std::make_unique<I18nAddon>(); 1382 status = 1383 napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()), I18nAddon::Destructor, nullptr, nullptr); 1384 if (status != napi_ok) { 1385 HILOG_ERROR_I18N("IndexUtilConstructor: Wrap II18nAddon failed"); 1386 return nullptr; 1387 } 1388 if (!obj->InitIndexUtilContext(env, info, localeTag)) { 1389 return nullptr; 1390 } 1391 obj.release(); 1392 return thisVar; 1393} 1394 1395bool I18nAddon::InitIndexUtilContext(napi_env env, napi_callback_info info, const std::string &localeTag) 1396{ 1397 napi_value global = nullptr; 1398 napi_status status = napi_get_global(env, &global); 1399 if (status != napi_ok) { 1400 HILOG_ERROR_I18N("InitIndexUtilContext: Get global failed"); 1401 return false; 1402 } 1403 env_ = env; 1404 indexUtil_ = std::make_unique<IndexUtil>(localeTag); 1405 return indexUtil_ != nullptr; 1406} 1407 1408napi_value I18nAddon::GetIndexUtil(napi_env env, napi_callback_info info) 1409{ 1410 size_t argc = 1; 1411 napi_value argv[1] = { 0 }; 1412 napi_value thisVar = nullptr; 1413 void *data = nullptr; 1414 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 1415 napi_value constructor = nullptr; 1416 napi_status status = napi_get_reference_value(env, g_indexUtilConstructor, &constructor); 1417 if (status != napi_ok) { 1418 HILOG_ERROR_I18N("Failed to create reference at GetIndexUtil"); 1419 return nullptr; 1420 } 1421 napi_value result = nullptr; 1422 if (!VariableConvertor::CheckNapiValueType(env, argv[0])) { 1423 status = napi_new_instance(env, constructor, 0, argv, &result); 1424 } else { 1425 status = napi_new_instance(env, constructor, 1, argv, &result); 1426 } 1427 if (status != napi_ok) { 1428 HILOG_ERROR_I18N("Get calendar create instance failed"); 1429 return nullptr; 1430 } 1431 return result; 1432} 1433 1434napi_value I18nAddon::GetIndexList(napi_env env, napi_callback_info info) 1435{ 1436 napi_value thisVar = nullptr; 1437 void *data = nullptr; 1438 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data); 1439 1440 I18nAddon *obj = nullptr; 1441 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj)); 1442 if (status != napi_ok || !obj || !obj->indexUtil_) { 1443 HILOG_ERROR_I18N("GetIndexList: GetPhoneNumberFormat object failed"); 1444 return nullptr; 1445 } 1446 1447 std::vector<std::string> indexList = obj->indexUtil_->GetIndexList(); 1448 napi_value result = nullptr; 1449 status = napi_create_array_with_length(env, indexList.size(), &result); 1450 if (status != napi_ok) { 1451 HILOG_ERROR_I18N("Failed to create array"); 1452 return nullptr; 1453 } 1454 for (size_t i = 0; i < indexList.size(); i++) { 1455 napi_value element = nullptr; 1456 status = napi_create_string_utf8(env, indexList[i].c_str(), NAPI_AUTO_LENGTH, &element); 1457 if (status != napi_ok) { 1458 HILOG_ERROR_I18N("GetIndexList: Failed to create string item"); 1459 return nullptr; 1460 } 1461 status = napi_set_element(env, result, i, element); 1462 if (status != napi_ok) { 1463 HILOG_ERROR_I18N("Failed to set array item"); 1464 return nullptr; 1465 } 1466 } 1467 return result; 1468} 1469 1470napi_value I18nAddon::AddLocale(napi_env env, napi_callback_info info) 1471{ 1472 size_t argc = 1; 1473 napi_value argv[1] = { 0 }; 1474 napi_value thisVar = nullptr; 1475 void *data = nullptr; 1476 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 1477 napi_valuetype valueType = napi_valuetype::napi_undefined; 1478 napi_typeof(env, argv[0], &valueType); 1479 if (valueType != napi_valuetype::napi_string) { 1480 HILOG_ERROR_I18N("AddLocale: Parameter type does not match"); 1481 return nullptr; 1482 } 1483 size_t len = 0; 1484 napi_status status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len); 1485 if (status != napi_ok) { 1486 HILOG_ERROR_I18N("AddLocale: Get locale length failed"); 1487 return nullptr; 1488 } 1489 std::vector<char> buf(len + 1); 1490 status = napi_get_value_string_utf8(env, argv[0], buf.data(), len + 1, &len); 1491 if (status != napi_ok) { 1492 HILOG_ERROR_I18N("AddLocale: Get locale failed"); 1493 return nullptr; 1494 } 1495 I18nAddon *obj = nullptr; 1496 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj)); 1497 if (status != napi_ok || !obj || !obj->indexUtil_) { 1498 HILOG_ERROR_I18N("AddLocale: Get IndexUtil object failed"); 1499 return nullptr; 1500 } 1501 obj->indexUtil_->AddLocale(buf.data()); 1502 return nullptr; 1503} 1504 1505napi_value I18nAddon::GetIndex(napi_env env, napi_callback_info info) 1506{ 1507 size_t argc = 1; 1508 napi_value argv[1] = { 0 }; 1509 napi_value thisVar = nullptr; 1510 void *data = nullptr; 1511 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data); 1512 napi_valuetype valueType = napi_valuetype::napi_undefined; 1513 napi_typeof(env, argv[0], &valueType); 1514 if (valueType != napi_valuetype::napi_string) { 1515 HILOG_ERROR_I18N("GetIndex: Parameter type does not match"); 1516 return nullptr; 1517 } 1518 size_t len = 0; 1519 napi_status status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len); 1520 if (status != napi_ok) { 1521 HILOG_ERROR_I18N("GetIndex: Get String length failed"); 1522 return nullptr; 1523 } 1524 std::vector<char> buf(len + 1); 1525 status = napi_get_value_string_utf8(env, argv[0], buf.data(), len + 1, &len); 1526 if (status != napi_ok) { 1527 HILOG_ERROR_I18N("Get String failed"); 1528 return nullptr; 1529 } 1530 I18nAddon *obj = nullptr; 1531 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj)); 1532 if (status != napi_ok || !obj || !obj->indexUtil_) { 1533 HILOG_ERROR_I18N("GetIndex: Get IndexUtil object failed"); 1534 return nullptr; 1535 } 1536 std::string index = obj->indexUtil_->GetIndex(buf.data()); 1537 napi_value result = nullptr; 1538 status = napi_create_string_utf8(env, index.c_str(), NAPI_AUTO_LENGTH, &result); 1539 if (status != napi_ok) { 1540 HILOG_ERROR_I18N("GetIndex Failed"); 1541 return nullptr; 1542 } 1543 return result; 1544} 1545 1546napi_value I18nAddon::ObjectConstructor(napi_env env, napi_callback_info info) 1547{ 1548 napi_value thisVar = nullptr; 1549 void *data = nullptr; 1550 napi_status status = napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data); 1551 if (status != napi_ok) { 1552 return nullptr; 1553 } 1554 std::unique_ptr<I18nAddon> obj = nullptr; 1555 obj = std::make_unique<I18nAddon>(); 1556 status = 1557 napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()), I18nAddon::Destructor, nullptr, nullptr); 1558 if (status != napi_ok) { 1559 HILOG_ERROR_I18N("ObjectConstructor: Wrap I18nAddon failed"); 1560 return nullptr; 1561 } 1562 obj.release(); 1563 return thisVar; 1564} 1565 1566napi_value I18nAddon::InitUtil(napi_env env, napi_value exports) 1567{ 1568 napi_status status = napi_ok; 1569 napi_property_descriptor properties[] = { 1570 DECLARE_NAPI_FUNCTION("unitConvert", UnitConvert) 1571 }; 1572 1573 napi_value constructor = nullptr; 1574 status = napi_define_class(env, "Util", NAPI_AUTO_LENGTH, ObjectConstructor, nullptr, 1575 sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor); 1576 if (status != napi_ok) { 1577 HILOG_ERROR_I18N("Define class failed when InitUtil"); 1578 return nullptr; 1579 } 1580 1581 status = napi_set_named_property(env, exports, "Util", constructor); 1582 if (status != napi_ok) { 1583 HILOG_ERROR_I18N("Set property failed when InitUtil"); 1584 return nullptr; 1585 } 1586 return exports; 1587} 1588 1589napi_value Init(napi_env env, napi_value exports) 1590{ 1591 napi_value val = I18nAddon::Init(env, exports); 1592 val = I18nAddon::InitPhoneNumberFormat(env, val); 1593 val = I18nAddon::InitI18nBreakIterator(env, val); 1594 val = I18nCalendarAddon::InitI18nCalendar(env, val); 1595 val = I18nAddon::InitI18nIndexUtil(env, val); 1596 val = I18nAddon::InitI18nUtil(env, val); 1597 val = I18nTimeZoneAddon::InitI18nTimeZone(env, val); 1598 val = I18nAddon::InitI18nTransliterator(env, val); 1599 val = I18nUnicodeAddon::InitCharacter(env, val); 1600 val = I18nUnicodeAddon::InitI18nUnicode(env, val); 1601 val = I18nAddon::InitUtil(env, val); 1602 val = I18nNormalizerAddon::InitI18nNormalizer(env, val); 1603 val = SystemLocaleManagerAddon::InitSystemLocaleManager(env, val); 1604 val = I18nSystemAddon::InitI18nSystem(env, val); 1605 val = HolidayManagerAddon::InitHolidayManager(env, val); 1606 val = EntityRecognizerAddon::InitEntityRecognizer(env, val); 1607 return val; 1608} 1609 1610static napi_module g_i18nModule = { 1611 .nm_version = 1, 1612 .nm_flags = 0, 1613 .nm_filename = nullptr, 1614 .nm_register_func = Init, 1615 .nm_modname = "i18n", 1616 .nm_priv = nullptr, 1617 .reserved = { 0 } 1618}; 1619 1620extern "C" __attribute__((constructor)) void I18nRegister() 1621{ 1622 napi_module_register(&g_i18nModule); 1623} 1624} // namespace I18n 1625} // namespace Global 1626} // namespace OHOS 1627