• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <chrono>
16 #include <unordered_map>
17 #include <vector>
18 
19 #include "character.h"
20 #include "hilog/log.h"
21 #include "i18n_calendar.h"
22 #include "i18n_normalizer_addon.h"
23 #include "system_locale_manager_addon.h"
24 #include "unicode/locid.h"
25 #include "unicode/datefmt.h"
26 #include "unicode/smpdtfmt.h"
27 #include "unicode/translit.h"
28 #include "node_api.h"
29 
30 #include "error_util.h"
31 #include "i18n_addon.h"
32 
33 namespace OHOS {
34 namespace Global {
35 namespace I18n {
36 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, 0xD001E00, "I18nJs" };
37 using namespace OHOS::HiviewDFX;
38 
39 static thread_local napi_ref* g_constructor = nullptr;
40 static thread_local napi_ref* g_brkConstructor = nullptr;
41 static thread_local napi_ref* g_timezoneConstructor = nullptr;
42 static thread_local napi_ref g_indexUtilConstructor = nullptr;
43 static thread_local napi_ref* g_transConstructor = nullptr;
44 static std::unordered_map<std::string, UCalendarDateFields> g_fieldsMap {
45     { "era", UCAL_ERA },
46     { "year", UCAL_YEAR },
47     { "month", UCAL_MONTH },
48     { "week_of_year", UCAL_WEEK_OF_YEAR },
49     { "week_of_month", UCAL_WEEK_OF_MONTH },
50     { "date", UCAL_DATE },
51     { "day_of_year", UCAL_DAY_OF_YEAR },
52     { "day_of_week", UCAL_DAY_OF_WEEK },
53     { "day_of_week_in_month", UCAL_DAY_OF_WEEK_IN_MONTH },
54     { "ap_pm", UCAL_AM_PM },
55     { "hour", UCAL_HOUR },
56     { "hour_of_day", UCAL_HOUR_OF_DAY },
57     { "minute", UCAL_MINUTE },
58     { "second", UCAL_SECOND },
59     { "millisecond", UCAL_MILLISECOND },
60     { "zone_offset", UCAL_ZONE_OFFSET },
61     { "dst_offset", UCAL_DST_OFFSET },
62     { "year_woy", UCAL_YEAR_WOY },
63     { "dow_local", UCAL_DOW_LOCAL },
64     { "extended_year", UCAL_EXTENDED_YEAR },
65     { "julian_day", UCAL_JULIAN_DAY },
66     { "milliseconds_in_day", UCAL_MILLISECONDS_IN_DAY },
67     { "is_leap_month", UCAL_IS_LEAP_MONTH },
68 };
69 static std::unordered_set<std::string> g_fieldsInFunctionAdd {
70     "year", "month", "date", "hour", "minute", "second", "millisecond",
71     "week_of_year", "week_of_month", "day_of_year", "day_of_week", "day_of_week_in_month",
72     "hour_of_day", "milliseconds_in_day",
73 };
74 static std::unordered_map<std::string, CalendarType> g_typeMap {
75     { "buddhist", CalendarType::BUDDHIST },
76     { "chinese", CalendarType::CHINESE },
77     { "coptic", CalendarType::COPTIC },
78     { "ethiopic", CalendarType::ETHIOPIC },
79     { "hebrew", CalendarType::HEBREW },
80     { "gregory", CalendarType::GREGORY },
81     { "indian", CalendarType::INDIAN },
82     { "islamic_civil", CalendarType::ISLAMIC_CIVIL },
83     { "islamic_tbla", CalendarType::ISLAMIC_TBLA },
84     { "islamic_umalqura", CalendarType::ISLAMIC_UMALQURA },
85     { "japanese", CalendarType::JAPANESE },
86     { "persion", CalendarType::PERSIAN },
87 };
88 
I18nAddon()89 I18nAddon::I18nAddon() : env_(nullptr) {}
90 
~I18nAddon()91 I18nAddon::~I18nAddon()
92 {
93 }
94 
Destructor(napi_env env,void * nativeObject,void * hint)95 void I18nAddon::Destructor(napi_env env, void *nativeObject, void *hint)
96 {
97     if (!nativeObject) {
98         return;
99     }
100     delete reinterpret_cast<I18nAddon *>(nativeObject);
101     nativeObject = nullptr;
102 }
103 
CreateUnicodeObject(napi_env env,napi_status & initStatus)104 napi_value I18nAddon::CreateUnicodeObject(napi_env env, napi_status &initStatus)
105 {
106     napi_status status = napi_ok;
107     napi_value character = nullptr;
108     status = napi_create_object(env, &character);
109     if (status != napi_ok) {
110         HiLog::Error(LABEL, "Failed to create character object at init");
111         initStatus = napi_generic_failure;
112         return nullptr;
113     }
114     napi_property_descriptor characterProperties[] = {
115         DECLARE_NAPI_FUNCTION("isDigit", IsDigitAddon),
116         DECLARE_NAPI_FUNCTION("isSpaceChar", IsSpaceCharAddon),
117         DECLARE_NAPI_FUNCTION("isWhitespace", IsWhiteSpaceAddon),
118         DECLARE_NAPI_FUNCTION("isRTL", IsRTLCharacterAddon),
119         DECLARE_NAPI_FUNCTION("isIdeograph", IsIdeoGraphicAddon),
120         DECLARE_NAPI_FUNCTION("isLetter", IsLetterAddon),
121         DECLARE_NAPI_FUNCTION("isLowerCase", IsLowerCaseAddon),
122         DECLARE_NAPI_FUNCTION("isUpperCase", IsUpperCaseAddon),
123         DECLARE_NAPI_FUNCTION("getType", GetTypeAddon),
124     };
125     status = napi_define_properties(env, character,
126                                     sizeof(characterProperties) / sizeof(napi_property_descriptor),
127                                     characterProperties);
128     if (status != napi_ok) {
129         HiLog::Error(LABEL, "Failed to set properties of character at init");
130         initStatus = napi_generic_failure;
131         return nullptr;
132     }
133     return character;
134 }
135 
CreateI18nUtilObject(napi_env env,napi_status & initStatus)136 napi_value I18nAddon::CreateI18nUtilObject(napi_env env, napi_status &initStatus)
137 {
138     napi_value i18nUtil = nullptr;
139     napi_status status = napi_create_object(env, &i18nUtil);
140     if (status != napi_ok) {
141         HiLog::Error(LABEL, "Failed to create I18nUtil object at init");
142         initStatus = napi_generic_failure;
143         return nullptr;
144     }
145     napi_property_descriptor i18nUtilProperties[] = {
146         DECLARE_NAPI_FUNCTION("unitConvert", UnitConvert),
147         DECLARE_NAPI_FUNCTION("getDateOrder", GetDateOrder)
148     };
149     status = napi_define_properties(env, i18nUtil, sizeof(i18nUtilProperties) / sizeof(napi_property_descriptor),
150         i18nUtilProperties);
151     if (status != napi_ok) {
152         HiLog::Error(LABEL, "Failed to set properties of I18nUtil at init");
153         initStatus = napi_generic_failure;
154         return nullptr;
155     }
156     return i18nUtil;
157 }
158 
Init(napi_env env,napi_value exports)159 napi_value I18nAddon::Init(napi_env env, napi_value exports)
160 {
161     napi_status initStatus = napi_ok;
162     napi_property_descriptor properties[] = {
163         DECLARE_NAPI_FUNCTION("getDisplayLanguage", GetDisplayLanguage),
164         DECLARE_NAPI_FUNCTION("getDisplayCountry", GetDisplayCountry),
165         DECLARE_NAPI_FUNCTION("getSystemLanguage", GetSystemLanguage),
166         DECLARE_NAPI_FUNCTION("getSystemRegion", GetSystemRegion),
167         DECLARE_NAPI_FUNCTION("getSystemLocale", GetSystemLocale),
168         DECLARE_NAPI_FUNCTION("getCalendar", GetCalendar),
169         DECLARE_NAPI_FUNCTION("isRTL", IsRTL),
170         DECLARE_NAPI_PROPERTY("I18NUtil", CreateI18nUtilObject(env, initStatus)),
171         DECLARE_NAPI_FUNCTION("getLineInstance", GetLineInstance),
172         DECLARE_NAPI_FUNCTION("getInstance", GetIndexUtil),
173         DECLARE_NAPI_PROPERTY("Unicode", CreateUnicodeObject(env, initStatus)),
174         DECLARE_NAPI_FUNCTION("addPreferredLanguage", AddPreferredLanguage),
175         DECLARE_NAPI_FUNCTION("removePreferredLanguage", RemovePreferredLanguage),
176         DECLARE_NAPI_FUNCTION("getPreferredLanguageList", GetPreferredLanguageList),
177         DECLARE_NAPI_FUNCTION("getFirstPreferredLanguage", GetFirstPreferredLanguage),
178         DECLARE_NAPI_FUNCTION("is24HourClock", Is24HourClock),
179         DECLARE_NAPI_FUNCTION("set24HourClock", Set24HourClock),
180         DECLARE_NAPI_FUNCTION("getTimeZone", GetI18nTimeZone),
181         DECLARE_NAPI_PROPERTY("Transliterator", CreateTransliteratorObject(env, initStatus)),
182         DECLARE_NAPI_PROPERTY("TimeZone", CreateTimeZoneObject(env, initStatus)),
183         DECLARE_NAPI_PROPERTY("System", CreateSystemObject(env, initStatus)),
184         DECLARE_NAPI_PROPERTY("NormalizerMode", I18nNormalizerAddon::CreateI18NNormalizerModeEnum(env, initStatus))
185     };
186     initStatus = napi_define_properties(env, exports, sizeof(properties) / sizeof(napi_property_descriptor),
187         properties);
188     if (initStatus != napi_ok) {
189         HiLog::Error(LABEL, "Failed to set properties at init");
190         return nullptr;
191     }
192     return exports;
193 }
194 
GetOptionValue(napi_env env,napi_value options,const std::string & optionName,std::string & value)195 void GetOptionValue(napi_env env, napi_value options, const std::string &optionName,
196     std::string &value)
197 {
198     napi_value optionValue = nullptr;
199     napi_valuetype type = napi_undefined;
200     napi_status status = napi_typeof(env, options, &type);
201     if (status != napi_ok && type != napi_object) {
202         HiLog::Error(LABEL, "Get option failed, option is not an object");
203         return;
204     }
205     bool hasProperty = false;
206     napi_status propStatus = napi_has_named_property(env, options, optionName.c_str(), &hasProperty);
207     if (propStatus == napi_ok && hasProperty) {
208         status = napi_get_named_property(env, options, optionName.c_str(), &optionValue);
209         if (status == napi_ok) {
210             size_t len;
211             napi_get_value_string_utf8(env, optionValue, nullptr, 0, &len);
212             std::vector<char> optionBuf(len + 1);
213             status = napi_get_value_string_utf8(env, optionValue, optionBuf.data(), len + 1, &len);
214             if (status != napi_ok) {
215                 HiLog::Error(LABEL, "Failed to get string item");
216                 return;
217             }
218             value = optionBuf.data();
219         }
220     }
221 }
222 
GetOptionMap(napi_env env,napi_value option,std::map<std::string,std::string> & map)223 void GetOptionMap(napi_env env, napi_value option, std::map<std::string, std::string> &map)
224 {
225     if (CheckNapiValueType(env, option)) {
226         size_t len;
227         napi_get_value_string_utf8(env, option, nullptr, 0, &len);
228         std::vector<char> styleBuf(len + 1);
229         napi_status status = napi_get_value_string_utf8(env, option, styleBuf.data(), len + 1, &len);
230         if (status != napi_ok) {
231             HiLog::Error(LABEL, "Failed to get string item");
232             return;
233         }
234         map.insert(std::make_pair("unitDisplay", styleBuf.data()));
235     }
236 }
237 
CheckNapiValueType(napi_env env,napi_value value)238 bool CheckNapiValueType(napi_env env, napi_value value)
239 {
240     if (value) {
241         napi_valuetype valueType = napi_valuetype::napi_undefined;
242         napi_typeof(env, value, &valueType);
243         if (valueType != napi_valuetype::napi_undefined && valueType != napi_valuetype::napi_null) {
244             return true;
245         }
246     }
247     return false;
248 }
249 
UnitConvert(napi_env env,napi_callback_info info)250 napi_value I18nAddon::UnitConvert(napi_env env, napi_callback_info info)
251 {
252     size_t argc = 5;
253     napi_value argv[5] = { 0 };
254     napi_value thisVar = nullptr;
255     void *data = nullptr;
256     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
257     if (status != napi_ok) {
258         return nullptr;
259     }
260     std::string fromUnit;
261     GetOptionValue(env, argv[0], "unit", fromUnit);
262     std::string fromMeasSys;
263     GetOptionValue(env, argv[0], "measureSystem", fromMeasSys);
264     std::string toUnit;
265     GetOptionValue(env, argv[1], "unit", toUnit);
266     std::string toMeasSys;
267     GetOptionValue(env, argv[1], "measureSystem", toMeasSys);
268     double number = 0;
269     napi_get_value_double(env, argv[2], &number); // 2 is the index of value
270     int convertStatus = Convert(number, fromUnit, fromMeasSys, toUnit, toMeasSys);
271     size_t len;
272     napi_get_value_string_utf8(env, argv[3], nullptr, 0, &len); // 3 is the index of value
273     std::vector<char> localeBuf(len + 1);
274     // 3 is the index of value
275     status = napi_get_value_string_utf8(env, argv[3], localeBuf.data(), len + 1, &len);
276     if (status != napi_ok) {
277         return nullptr;
278     }
279     std::vector<std::string> localeTags;
280     localeTags.push_back(localeBuf.data());
281     std::map<std::string, std::string> map = {};
282     map.insert(std::make_pair("style", "unit"));
283     if (!convertStatus) {
284         map.insert(std::make_pair("unit", fromUnit));
285     } else {
286         map.insert(std::make_pair("unit", toUnit));
287     }
288     // 4 is the index of value
289     GetOptionMap(env, argv[4], map);
290     std::unique_ptr<NumberFormat> numberFmt = nullptr;
291     numberFmt = std::make_unique<NumberFormat>(localeTags, map);
292     std::string value = numberFmt->Format(number);
293     napi_value result;
294     status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result);
295     if (status != napi_ok) {
296         HiLog::Error(LABEL, "Failed to create string item");
297         return nullptr;
298     }
299     return result;
300 }
301 
GetDateOrder(napi_env env,napi_callback_info info)302 napi_value I18nAddon::GetDateOrder(napi_env env, napi_callback_info info)
303 {
304     size_t argc = 1;
305     napi_value argv[1] = { 0 };
306     napi_value thisVar = nullptr;
307     void *data = nullptr;
308     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
309     if (status != napi_ok) {
310         return nullptr;
311     }
312     size_t len = 0;
313     napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len);
314     std::vector<char> languageBuf(len + 1);
315     status = napi_get_value_string_utf8(env, argv[0], languageBuf.data(), len + 1, &len);
316     if (status != napi_ok) {
317         HiLog::Error(LABEL, "Failed to get locale string for GetDateOrder");
318         return nullptr;
319     }
320     UErrorCode icuStatus = U_ZERO_ERROR;
321     icu::Locale locale = icu::Locale::forLanguageTag(languageBuf.data(), icuStatus);
322     if (icuStatus != U_ZERO_ERROR) {
323         HiLog::Error(LABEL, "Failed to create locale for GetDateOrder");
324         return nullptr;
325     }
326     icu::SimpleDateFormat* formatter = dynamic_cast<icu::SimpleDateFormat*>
327         (icu::DateFormat::createDateInstance(icu::DateFormat::EStyle::kDefault, locale));
328     if (icuStatus != U_ZERO_ERROR || formatter == nullptr) {
329         HiLog::Error(LABEL, "Failed to create SimpleDateFormat");
330         return nullptr;
331     }
332     std::string tempValue;
333     icu::UnicodeString unistr;
334     formatter->toPattern(unistr);
335     unistr.toUTF8String<std::string>(tempValue);
336     std::string value = ModifyOrder(tempValue);
337     napi_value result;
338     status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result);
339     if (status != napi_ok) {
340         HiLog::Error(LABEL, "Failed to create string item");
341         return nullptr;
342     }
343     return result;
344 }
345 
ModifyOrder(std::string & pattern)346 std::string I18nAddon::ModifyOrder(std::string &pattern)
347 {
348     int order[3] = { 0 }; // total 3 elements 'y', 'M'/'L', 'd'
349     int lengths[4] = { 0 }; // first elements is the currently found elememnts, thus 4 elements totally.
350     bool flag = true;
351     for (size_t i = 0; i < pattern.length(); ++i) {
352         char ch = pattern[i];
353         if (flag && std::isalpha(ch)) {
354             ProcessNormal(ch, order, 3, lengths, 4); // 3, 4 are lengths of these arrays
355         } else if (ch == '\'') {
356             flag = !flag;
357         }
358     }
359     std::unordered_map<char, int> pattern2index = {
360         { 'y', 1 },
361         { 'L', 2 },
362         { 'd', 3 },
363     };
364     std::string ret;
365     for (int i = 0; i < 3; ++i) { // 3 is the size of orders
366         auto it = pattern2index.find(order[i]);
367         if (it == pattern2index.end()) {
368             continue;
369         }
370         int index = it->second;
371         if ((lengths[index] > 0) && (lengths[index] <= 6)) { // 6 is the max length of a filed
372             ret.append(lengths[index], order[i]);
373         }
374         if (i < 2) { // 2 is the size of the order minus one
375             ret.append(1, '-');
376         }
377     }
378     return ret;
379 }
380 
ProcessNormal(char ch,int * order,size_t orderSize,int * lengths,size_t lengsSize)381 void I18nAddon::ProcessNormal(char ch, int *order, size_t orderSize, int *lengths, size_t lengsSize)
382 {
383     char adjust;
384     int index = -1;
385     if (ch == 'd') {
386         adjust = 'd';
387         index = 3; // 3 is the index of 'd'
388     } else if ((ch == 'L') || (ch == 'M')) {
389         adjust = 'L';
390         index = 2; // 2 is the index of 'L'
391     } else if (ch == 'y') {
392         adjust = 'y';
393         index = 1;
394     } else {
395         return;
396     }
397     if ((index < 0) || (index >= static_cast<int>(lengsSize))) {
398         return;
399     }
400     if (lengths[index] == 0) {
401         if (lengths[0] >= 3) { // 3 is the index of order
402             return;
403         }
404         order[lengths[0]] = static_cast<int>(adjust);
405         ++lengths[0];
406         lengths[index] = 1;
407     } else {
408         ++lengths[index];
409     }
410 }
411 
InitTransliterator(napi_env env,napi_value exports)412 napi_value I18nAddon::InitTransliterator(napi_env env, napi_value exports)
413 {
414     napi_status status = napi_ok;
415     napi_property_descriptor properties[] = {
416         DECLARE_NAPI_FUNCTION("transform", Transform),
417     };
418     napi_value constructor = nullptr;
419     status = napi_define_class(env, "Transliterator", NAPI_AUTO_LENGTH, TransliteratorConstructor, nullptr,
420         sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor);
421     if (status != napi_ok) {
422         HiLog::Error(LABEL, "Failed to define transliterator class at Init");
423         return nullptr;
424     }
425     g_transConstructor = new (std::nothrow) napi_ref;
426     if (!g_transConstructor) {
427         HiLog::Error(LABEL, "Failed to create trans ref at init");
428         return nullptr;
429     }
430     status = napi_create_reference(env, constructor, 1, g_transConstructor);
431     if (status != napi_ok) {
432         HiLog::Error(LABEL, "Failed to create trans reference at init");
433         return nullptr;
434     }
435     return exports;
436 }
437 
TransliteratorConstructor(napi_env env,napi_callback_info info)438 napi_value I18nAddon::TransliteratorConstructor(napi_env env, napi_callback_info info)
439 {
440     size_t argc = 1;
441     napi_value argv[1] = { 0 };
442     napi_value thisVar = nullptr;
443     void *data = nullptr;
444     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
445     if (status != napi_ok) {
446         return nullptr;
447     }
448     napi_valuetype valueType = napi_valuetype::napi_undefined;
449     napi_typeof(env, argv[0], &valueType);
450     if (valueType != napi_valuetype::napi_string) {
451         napi_throw_type_error(env, nullptr, "Parameter type does not match");
452         return nullptr;
453     }
454     int32_t code = 0;
455     std::string idTag = GetString(env, argv[0], code);
456     if (code) {
457         return nullptr;
458     }
459     std::unique_ptr<I18nAddon> obj = nullptr;
460     obj = std::make_unique<I18nAddon>();
461     status =
462         napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()), I18nAddon::Destructor, nullptr, nullptr);
463     if (status != napi_ok) {
464         HiLog::Error(LABEL, "TransliteratorConstructor: Wrap II18nAddon failed");
465         return nullptr;
466     }
467     if (!obj->InitTransliteratorContext(env, info, idTag)) {
468         obj.release();
469         return nullptr;
470     }
471     obj.release();
472     return thisVar;
473 }
474 
InitTransliteratorContext(napi_env env,napi_callback_info info,const std::string & idTag)475 bool I18nAddon::InitTransliteratorContext(napi_env env, napi_callback_info info, const std::string &idTag)
476 {
477     UErrorCode status = U_ZERO_ERROR;
478     icu::UnicodeString unistr = icu::UnicodeString::fromUTF8(idTag);
479     icu::Transliterator *trans = icu::Transliterator::createInstance(unistr, UTransDirection::UTRANS_FORWARD, status);
480     if ((status != U_ZERO_ERROR) || (trans == nullptr)) {
481         return false;
482     }
483     transliterator_ = std::unique_ptr<icu::Transliterator>(trans);
484     return transliterator_ != nullptr;
485 }
486 
CreateTransliteratorObject(napi_env env,napi_status & initStatus)487 napi_value I18nAddon::CreateTransliteratorObject(napi_env env, napi_status &initStatus)
488 {
489     napi_status status = napi_ok;
490     napi_value transliterator = nullptr;
491     status = napi_create_object(env, &transliterator);
492     if (status != napi_ok) {
493         HiLog::Error(LABEL, "Failed to create transliterator object at init");
494         initStatus = napi_generic_failure;
495         return nullptr;
496     }
497     napi_property_descriptor transProperties[] = {
498         DECLARE_NAPI_FUNCTION("getAvailableIDs", GetAvailableIDs),
499         DECLARE_NAPI_FUNCTION("getInstance", GetTransliteratorInstance)
500     };
501     status = napi_define_properties(env, transliterator,
502                                     sizeof(transProperties) / sizeof(napi_property_descriptor),
503                                     transProperties);
504     if (status != napi_ok) {
505         HiLog::Error(LABEL, "Failed to set properties of transliterator at init");
506         initStatus = napi_generic_failure;
507         return nullptr;
508     }
509     return transliterator;
510 }
511 
Transform(napi_env env,napi_callback_info info)512 napi_value I18nAddon::Transform(napi_env env, napi_callback_info info)
513 {
514     size_t argc = 1;
515     napi_value argv[1] = { nullptr };
516     napi_value thisVar = nullptr;
517     void *data = nullptr;
518     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
519     I18nAddon *obj = nullptr;
520     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
521     if (status != napi_ok || !obj || !obj->transliterator_) {
522         HiLog::Error(LABEL, "Get Transliterator object failed");
523         return nullptr;
524     }
525     if (!argv[0]) {
526         return nullptr;
527     }
528     napi_valuetype valueType = napi_valuetype::napi_undefined;
529     napi_typeof(env, argv[0], &valueType);
530     if (valueType != napi_valuetype::napi_string) {
531         napi_throw_type_error(env, nullptr, "Parameter type does not match");
532         return nullptr;
533     }
534     size_t len = 0;
535     status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len);
536     if (status != napi_ok) {
537         HiLog::Error(LABEL, "Get field length failed");
538         return nullptr;
539     }
540     std::vector<char> buf(len + 1);
541     status = napi_get_value_string_utf8(env, argv[0], buf.data(), len + 1, &len);
542     if (status != napi_ok) {
543         HiLog::Error(LABEL, "Get string value failed");
544         return nullptr;
545     }
546     icu::UnicodeString unistr = icu::UnicodeString::fromUTF8(buf.data());
547     obj->transliterator_->transliterate(unistr);
548     std::string temp;
549     unistr.toUTF8String(temp);
550     napi_value value;
551     status = napi_create_string_utf8(env, temp.c_str(), NAPI_AUTO_LENGTH, &value);
552     if (status != napi_ok) {
553         HiLog::Error(LABEL, "Get field length failed");
554         return nullptr;
555     }
556     return value;
557 }
558 
GetAvailableIDs(napi_env env,napi_callback_info info)559 napi_value I18nAddon::GetAvailableIDs(napi_env env, napi_callback_info info)
560 {
561     size_t argc = 0;
562     napi_value *argv = nullptr;
563     napi_value thisVar = nullptr;
564     void *data = nullptr;
565     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
566     if (status != napi_ok) {
567         return nullptr;
568     }
569     UErrorCode icuStatus = U_ZERO_ERROR;
570     icu::StringEnumeration *strenum = icu::Transliterator::getAvailableIDs(icuStatus);
571     if (icuStatus != U_ZERO_ERROR) {
572         HiLog::Error(LABEL, "Failed to get available ids");
573         if (strenum) {
574             delete strenum;
575         }
576         return nullptr;
577     }
578 
579     napi_value result = nullptr;
580     napi_create_array(env, &result);
581     uint32_t i = 0;
582     const char *temp = nullptr;
583     if (strenum == nullptr) {
584         return nullptr;
585     }
586     while ((temp = strenum->next(nullptr, icuStatus)) != nullptr) {
587         if (icuStatus != U_ZERO_ERROR) {
588             break;
589         }
590         napi_value val = nullptr;
591         napi_create_string_utf8(env, temp, strlen(temp), &val);
592         napi_set_element(env, result, i, val);
593         ++i;
594     }
595     delete strenum;
596     return result;
597 }
598 
GetTransliteratorInstance(napi_env env,napi_callback_info info)599 napi_value I18nAddon::GetTransliteratorInstance(napi_env env, napi_callback_info info)
600 {
601     size_t argc = 1; // retrieve 2 arguments
602     napi_value argv[1] = { 0 };
603     napi_value thisVar = nullptr;
604     void *data = nullptr;
605     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
606     napi_value constructor = nullptr;
607     napi_status status = napi_get_reference_value(env, *g_transConstructor, &constructor);
608     if (status != napi_ok) {
609         HiLog::Error(LABEL, "Failed to create reference at GetCalendar");
610         return nullptr;
611     }
612     napi_value result = nullptr;
613     status = napi_new_instance(env, constructor, 1, argv, &result); // 2 arguments
614     if (status != napi_ok) {
615         HiLog::Error(LABEL, "Get Transliterator create instance failed");
616         return nullptr;
617     }
618     return result;
619 }
620 
IsDigitAddon(napi_env env,napi_callback_info info)621 napi_value I18nAddon::IsDigitAddon(napi_env env, napi_callback_info info)
622 {
623     size_t argc = 1;
624     napi_value argv[1] = { 0 };
625     napi_value thisVar = nullptr;
626     void *data = nullptr;
627     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
628     if (status != napi_ok) {
629         return nullptr;
630     }
631     napi_valuetype valueType = napi_valuetype::napi_undefined;
632     napi_typeof(env, argv[0], &valueType);
633     if (valueType != napi_valuetype::napi_string) {
634         napi_throw_type_error(env, nullptr, "Parameter type does not match");
635         return nullptr;
636     }
637     int32_t code = 0;
638     std::string character = GetString(env, argv[0], code);
639     if (code) {
640         return nullptr;
641     }
642     bool isDigit = IsDigit(character);
643     napi_value result = nullptr;
644     status = napi_get_boolean(env, isDigit, &result);
645     if (status != napi_ok) {
646         HiLog::Error(LABEL, "Create isDigit boolean value failed");
647         return nullptr;
648     }
649     return result;
650 }
651 
IsSpaceCharAddon(napi_env env,napi_callback_info info)652 napi_value I18nAddon::IsSpaceCharAddon(napi_env env, napi_callback_info info)
653 {
654     size_t argc = 1;
655     napi_value argv[1] = { 0 };
656     napi_value thisVar = nullptr;
657     void *data = nullptr;
658     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
659     if (status != napi_ok) {
660         return nullptr;
661     }
662     napi_valuetype valueType = napi_valuetype::napi_undefined;
663     napi_typeof(env, argv[0], &valueType);
664     if (valueType != napi_valuetype::napi_string) {
665         napi_throw_type_error(env, nullptr, "Parameter type does not match");
666         return nullptr;
667     }
668     int32_t code = 0;
669     std::string character = GetString(env, argv[0], code);
670     if (code) {
671         return nullptr;
672     }
673     bool isSpaceChar = IsSpaceChar(character);
674     napi_value result = nullptr;
675     status = napi_get_boolean(env, isSpaceChar, &result);
676     if (status != napi_ok) {
677         HiLog::Error(LABEL, "Create isSpaceChar boolean value failed");
678         return nullptr;
679     }
680     return result;
681 }
682 
IsWhiteSpaceAddon(napi_env env,napi_callback_info info)683 napi_value I18nAddon::IsWhiteSpaceAddon(napi_env env, napi_callback_info info)
684 {
685     size_t argc = 1;
686     napi_value argv[1] = { 0 };
687     napi_value thisVar = nullptr;
688     void *data = nullptr;
689     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
690     if (status != napi_ok) {
691         return nullptr;
692     }
693     napi_valuetype valueType = napi_valuetype::napi_undefined;
694     napi_typeof(env, argv[0], &valueType);
695     if (valueType != napi_valuetype::napi_string) {
696         napi_throw_type_error(env, nullptr, "Parameter type does not match");
697         return nullptr;
698     }
699     int32_t code = 0;
700     std::string character = GetString(env, argv[0], code);
701     if (code) {
702         return nullptr;
703     }
704     bool isWhiteSpace = IsWhiteSpace(character);
705     napi_value result = nullptr;
706     status = napi_get_boolean(env, isWhiteSpace, &result);
707     if (status != napi_ok) {
708         HiLog::Error(LABEL, "Create isWhiteSpace boolean value failed");
709         return nullptr;
710     }
711     return result;
712 }
713 
IsRTLCharacterAddon(napi_env env,napi_callback_info info)714 napi_value I18nAddon::IsRTLCharacterAddon(napi_env env, napi_callback_info info)
715 {
716     size_t argc = 1;
717     napi_value argv[1] = { 0 };
718     napi_value thisVar = nullptr;
719     void *data = nullptr;
720     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
721     if (status != napi_ok) {
722         return nullptr;
723     }
724     napi_valuetype valueType = napi_valuetype::napi_undefined;
725     napi_typeof(env, argv[0], &valueType);
726     if (valueType != napi_valuetype::napi_string) {
727         napi_throw_type_error(env, nullptr, "Parameter type does not match");
728         return nullptr;
729     }
730     int32_t code = 0;
731     std::string character = GetString(env, argv[0], code);
732     if (code) {
733         return nullptr;
734     }
735     bool isRTLCharacter = IsRTLCharacter(character);
736     napi_value result = nullptr;
737     status = napi_get_boolean(env, isRTLCharacter, &result);
738     if (status != napi_ok) {
739         HiLog::Error(LABEL, "Create isRTLCharacter boolean value failed");
740         return nullptr;
741     }
742     return result;
743 }
744 
IsIdeoGraphicAddon(napi_env env,napi_callback_info info)745 napi_value I18nAddon::IsIdeoGraphicAddon(napi_env env, napi_callback_info info)
746 {
747     size_t argc = 1;
748     napi_value argv[1] = { 0 };
749     napi_value thisVar = nullptr;
750     void *data = nullptr;
751     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
752     if (status != napi_ok) {
753         return nullptr;
754     }
755     napi_valuetype valueType = napi_valuetype::napi_undefined;
756     napi_typeof(env, argv[0], &valueType);
757     if (valueType != napi_valuetype::napi_string) {
758         napi_throw_type_error(env, nullptr, "Parameter type does not match");
759         return nullptr;
760     }
761     int32_t code = 0;
762     std::string character = GetString(env, argv[0], code);
763     if (code) {
764         return nullptr;
765     }
766     bool isIdeoGraphic = IsIdeoGraphic(character);
767     napi_value result = nullptr;
768     status = napi_get_boolean(env, isIdeoGraphic, &result);
769     if (status != napi_ok) {
770         HiLog::Error(LABEL, "Create isIdeoGraphic boolean value failed");
771         return nullptr;
772     }
773     return result;
774 }
775 
IsLetterAddon(napi_env env,napi_callback_info info)776 napi_value I18nAddon::IsLetterAddon(napi_env env, napi_callback_info info)
777 {
778     size_t argc = 1;
779     napi_value argv[1] = { 0 };
780     napi_value thisVar = nullptr;
781     void *data = nullptr;
782     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
783     if (status != napi_ok) {
784         return nullptr;
785     }
786     napi_valuetype valueType = napi_valuetype::napi_undefined;
787     napi_typeof(env, argv[0], &valueType);
788     if (valueType != napi_valuetype::napi_string) {
789         napi_throw_type_error(env, nullptr, "Parameter type does not match");
790         return nullptr;
791     }
792     int32_t code = 0;
793     std::string character = GetString(env, argv[0], code);
794     if (code) {
795         return nullptr;
796     }
797     bool isLetter = IsLetter(character);
798     napi_value result = nullptr;
799     status = napi_get_boolean(env, isLetter, &result);
800     if (status != napi_ok) {
801         HiLog::Error(LABEL, "Create isLetter boolean value failed");
802         return nullptr;
803     }
804     return result;
805 }
806 
IsLowerCaseAddon(napi_env env,napi_callback_info info)807 napi_value I18nAddon::IsLowerCaseAddon(napi_env env, napi_callback_info info)
808 {
809     size_t argc = 1;
810     napi_value argv[1] = { 0 };
811     napi_value thisVar = nullptr;
812     void *data = nullptr;
813     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
814     if (status != napi_ok) {
815         return nullptr;
816     }
817     napi_valuetype valueType = napi_valuetype::napi_undefined;
818     napi_typeof(env, argv[0], &valueType);
819     if (valueType != napi_valuetype::napi_string) {
820         napi_throw_type_error(env, nullptr, "Parameter type does not match");
821         return nullptr;
822     }
823     int32_t code = 0;
824     std::string character = GetString(env, argv[0], code);
825     if (code) {
826         return nullptr;
827     }
828     bool isLowerCase = IsLowerCase(character);
829     napi_value result = nullptr;
830     status = napi_get_boolean(env, isLowerCase, &result);
831     if (status != napi_ok) {
832         HiLog::Error(LABEL, "Create isLowerCase boolean value failed");
833         return nullptr;
834     }
835     return result;
836 }
837 
IsUpperCaseAddon(napi_env env,napi_callback_info info)838 napi_value I18nAddon::IsUpperCaseAddon(napi_env env, napi_callback_info info)
839 {
840     size_t argc = 1;
841     napi_value argv[1] = { 0 };
842     napi_value thisVar = nullptr;
843     void *data = nullptr;
844     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
845     if (status != napi_ok) {
846         return nullptr;
847     }
848     napi_valuetype valueType = napi_valuetype::napi_undefined;
849     napi_typeof(env, argv[0], &valueType);
850     if (valueType != napi_valuetype::napi_string) {
851         napi_throw_type_error(env, nullptr, "Parameter type does not match");
852         return nullptr;
853     }
854     int32_t code = 0;
855     std::string character = GetString(env, argv[0], code);
856     if (code) {
857         return nullptr;
858     }
859     bool isUpperCase = IsUpperCase(character);
860     napi_value result = nullptr;
861     status = napi_get_boolean(env, isUpperCase, &result);
862     if (status != napi_ok) {
863         HiLog::Error(LABEL, "Create isUpperCase boolean value failed");
864         return nullptr;
865     }
866     return result;
867 }
868 
GetTypeAddon(napi_env env,napi_callback_info info)869 napi_value I18nAddon::GetTypeAddon(napi_env env, napi_callback_info info)
870 {
871     size_t argc = 1;
872     napi_value argv[1] = { 0 };
873     napi_value thisVar = nullptr;
874     void *data = nullptr;
875     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
876     if (status != napi_ok) {
877         return nullptr;
878     }
879     napi_valuetype valueType = napi_valuetype::napi_undefined;
880     napi_typeof(env, argv[0], &valueType);
881     if (valueType != napi_valuetype::napi_string) {
882         napi_throw_type_error(env, nullptr, "Parameter type does not match");
883         return nullptr;
884     }
885     int32_t code = 0;
886     std::string character = GetString(env, argv[0], code);
887     if (code) {
888         return nullptr;
889     }
890     std::string type = GetType(character);
891     napi_value result = nullptr;
892     status = napi_create_string_utf8(env, type.c_str(), NAPI_AUTO_LENGTH, &result);
893     if (status != napi_ok) {
894         HiLog::Error(LABEL, "Create getType string value failed");
895         return nullptr;
896     }
897     return result;
898 }
899 
GetSystemLanguages(napi_env env,napi_callback_info info)900 napi_value I18nAddon::GetSystemLanguages(napi_env env, napi_callback_info info)
901 {
902     std::vector<std::string> systemLanguages;
903     LocaleConfig::GetSystemLanguages(systemLanguages);
904     napi_value result = nullptr;
905     napi_status status = napi_create_array_with_length(env, systemLanguages.size(), &result);
906     if (status != napi_ok) {
907         HiLog::Error(LABEL, "Failed to create array");
908         return nullptr;
909     }
910     for (size_t i = 0; i < systemLanguages.size(); i++) {
911         napi_value value = nullptr;
912         status = napi_create_string_utf8(env, systemLanguages[i].c_str(), NAPI_AUTO_LENGTH, &value);
913         if (status != napi_ok) {
914             HiLog::Error(LABEL, "GetSystemLanguages: Failed to create string item");
915             return nullptr;
916         }
917         status = napi_set_element(env, result, i, value);
918         if (status != napi_ok) {
919             HiLog::Error(LABEL, "GetSystemLanguages: Failed to set array item");
920             return nullptr;
921         }
922     }
923     return result;
924 }
925 
GetSystemCountries(napi_env env,napi_callback_info info)926 napi_value I18nAddon::GetSystemCountries(napi_env env, napi_callback_info info)
927 {
928     return I18nAddon::GetSystemCountriesImpl(env, info, false);
929 }
930 
GetSystemCountriesWithError(napi_env env,napi_callback_info info)931 napi_value I18nAddon::GetSystemCountriesWithError(napi_env env, napi_callback_info info)
932 {
933     return I18nAddon::GetSystemCountriesImpl(env, info, true);
934 }
935 
GetSystemCountriesImpl(napi_env env,napi_callback_info info,bool throwError)936 napi_value I18nAddon::GetSystemCountriesImpl(napi_env env, napi_callback_info info, bool throwError)
937 {
938     size_t argc = 1;
939     napi_value argv[1] = { 0 };
940     napi_value thisVar = nullptr;
941     void *data = nullptr;
942     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
943     if (status != napi_ok) {
944         return nullptr;
945     }
946     if (argv[0] == nullptr) {
947         HiLog::Error(LABEL, "Missing parameter");
948         ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, throwError);
949         return nullptr;
950     }
951     size_t len = 0;
952     napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len);
953     std::vector<char> localeBuf(len + 1);
954     status = napi_get_value_string_utf8(env, argv[0], localeBuf.data(), len + 1, &len);
955     if (status != napi_ok) {
956         HiLog::Error(LABEL, "Failed to get string item");
957         ErrorUtil::NapiThrow(env, I18N_NOT_VALID, throwError);
958         return nullptr;
959     }
960     std::vector<std::string> systemCountries;
961     LocaleConfig::GetSystemCountries(systemCountries);
962     napi_value result = nullptr;
963     status = napi_create_array_with_length(env, systemCountries.size(), &result);
964     if (status != napi_ok) {
965         HiLog::Error(LABEL, "Failed to create array");
966         return nullptr;
967     }
968     for (size_t i = 0; i < systemCountries.size(); i++) {
969         napi_value value = nullptr;
970         status = napi_create_string_utf8(env, systemCountries[i].c_str(), NAPI_AUTO_LENGTH, &value);
971         if (status != napi_ok) {
972             HiLog::Error(LABEL, "GetSystemCountries: Failed to create string item");
973             return nullptr;
974         }
975         status = napi_set_element(env, result, i, value);
976         if (status != napi_ok) {
977             HiLog::Error(LABEL, "GetSystemCountries: Failed to set array item");
978             return nullptr;
979         }
980     }
981     return result;
982 }
983 
GetSystemLanguage(napi_env env,napi_callback_info info)984 napi_value I18nAddon::GetSystemLanguage(napi_env env, napi_callback_info info)
985 {
986     std::string value = LocaleConfig::GetSystemLanguage();
987     napi_value result = nullptr;
988     napi_status status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result);
989     if (status != napi_ok) {
990         HiLog::Error(LABEL, "Failed to create string item");
991         return nullptr;
992     }
993     return result;
994 }
995 
GetSystemRegion(napi_env env,napi_callback_info info)996 napi_value I18nAddon::GetSystemRegion(napi_env env, napi_callback_info info)
997 {
998     std::string value = LocaleConfig::GetSystemRegion();
999     napi_value result = nullptr;
1000     napi_status status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result);
1001     if (status != napi_ok) {
1002         HiLog::Error(LABEL, "Failed to create string item");
1003         return nullptr;
1004     }
1005     return result;
1006 }
1007 
GetSystemLocale(napi_env env,napi_callback_info info)1008 napi_value I18nAddon::GetSystemLocale(napi_env env, napi_callback_info info)
1009 {
1010     std::string value = LocaleConfig::GetSystemLocale();
1011     napi_value result = nullptr;
1012     napi_status status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result);
1013     if (status != napi_ok) {
1014         HiLog::Error(LABEL, "Failed to create string item");
1015         return nullptr;
1016     }
1017     return result;
1018 }
1019 
GetDisplayLanguage(napi_env env,napi_callback_info info)1020 napi_value I18nAddon::GetDisplayLanguage(napi_env env, napi_callback_info info)
1021 {
1022     return I18nAddon::GetDisplayLanguageImpl(env, info, false);
1023 }
1024 
GetDisplayLanguageWithError(napi_env env,napi_callback_info info)1025 napi_value I18nAddon::GetDisplayLanguageWithError(napi_env env, napi_callback_info info)
1026 {
1027     return I18nAddon::GetDisplayLanguageImpl(env, info, true);
1028 }
1029 
GetDisplayLanguageImpl(napi_env env,napi_callback_info info,bool throwError)1030 napi_value I18nAddon::GetDisplayLanguageImpl(napi_env env, napi_callback_info info, bool throwError)
1031 {
1032     // Need to get three parameters to get the display Language.
1033     size_t argc = 3;
1034     napi_value argv[3] = { 0 };
1035     napi_value thisVar = nullptr;
1036     void *data = nullptr;
1037     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1038     if (status != napi_ok) {
1039         return nullptr;
1040     }
1041     if (argv[1] == nullptr) {
1042         HiLog::Error(LABEL, "Missing parameter");
1043         ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, throwError);
1044         return nullptr;
1045     }
1046     size_t len = 0;
1047     napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len);
1048     std::vector<char> localeBuf(len + 1);
1049     status = napi_get_value_string_utf8(env, argv[0], localeBuf.data(), len + 1, &len);
1050     if (status != napi_ok) {
1051         HiLog::Error(LABEL, "Failed to get string item");
1052         ErrorUtil::NapiThrow(env, I18N_NOT_VALID, throwError);
1053         return nullptr;
1054     }
1055     napi_get_value_string_utf8(env, argv[1], nullptr, 0, &len);
1056     std::vector<char> displayLocaleBuf(len + 1);
1057     status = napi_get_value_string_utf8(env, argv[1], displayLocaleBuf.data(), len + 1, &len);
1058     if (status != napi_ok) {
1059         HiLog::Error(LABEL, "Failed to get string item");
1060         ErrorUtil::NapiThrow(env, I18N_NOT_VALID, throwError);
1061         return nullptr;
1062     }
1063     bool sentenceCase = true;
1064     int sentenceCaseIndex = 2;
1065     if (argv[sentenceCaseIndex] != nullptr) {
1066         napi_get_value_bool(env, argv[sentenceCaseIndex], &sentenceCase);
1067     }
1068 
1069     std::string value = LocaleConfig::GetDisplayLanguage(localeBuf.data(), displayLocaleBuf.data(), sentenceCase);
1070     if (value.length() == 0) {
1071         ErrorUtil::NapiThrow(env, I18N_NOT_VALID, throwError);
1072         return nullptr;
1073     }
1074     napi_value result = nullptr;
1075     status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result);
1076     if (status != napi_ok) {
1077         HiLog::Error(LABEL, "Failed to create string item");
1078         return nullptr;
1079     }
1080     return result;
1081 }
1082 
GetDisplayCountry(napi_env env,napi_callback_info info)1083 napi_value I18nAddon::GetDisplayCountry(napi_env env, napi_callback_info info)
1084 {
1085     return I18nAddon::GetDisplayCountryImpl(env, info, false);
1086 }
1087 
GetDisplayCountryWithError(napi_env env,napi_callback_info info)1088 napi_value I18nAddon::GetDisplayCountryWithError(napi_env env, napi_callback_info info)
1089 {
1090     return I18nAddon::GetDisplayCountryImpl(env, info, true);
1091 }
1092 
GetDisplayCountryImpl(napi_env env,napi_callback_info info,bool throwError)1093 napi_value I18nAddon::GetDisplayCountryImpl(napi_env env, napi_callback_info info, bool throwError)
1094 {
1095     // Need to get three parameters to get the display country.
1096     size_t argc = 3;
1097     napi_value argv[3] = { 0 };
1098     napi_value thisVar = nullptr;
1099     void *data = nullptr;
1100     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1101     if (status != napi_ok) {
1102         return nullptr;
1103     }
1104     if (argv[1] == nullptr) {
1105         HiLog::Error(LABEL, "Missing parameter");
1106         ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, throwError);
1107         return nullptr;
1108     }
1109     size_t len = 0;
1110     napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len);
1111     std::vector<char> localeBuf(len + 1);
1112     status = napi_get_value_string_utf8(env, argv[0], localeBuf.data(), len + 1, &len);
1113     if (status != napi_ok) {
1114         HiLog::Error(LABEL, "Failed to get string item");
1115         ErrorUtil::NapiThrow(env, I18N_NOT_VALID, throwError);
1116         return nullptr;
1117     }
1118     napi_get_value_string_utf8(env, argv[1], nullptr, 0, &len);
1119     std::vector<char> displayLocaleBuf(len + 1);
1120     status = napi_get_value_string_utf8(env, argv[1], displayLocaleBuf.data(), len + 1, &len);
1121     if (status != napi_ok) {
1122         HiLog::Error(LABEL, "Failed to get string item");
1123         ErrorUtil::NapiThrow(env, I18N_NOT_VALID, throwError);
1124         return nullptr;
1125     }
1126     bool sentenceCase = true;
1127     int sentenceCaseIndex = 2;
1128     if (argv[sentenceCaseIndex] != nullptr) {
1129         napi_get_value_bool(env, argv[sentenceCaseIndex], &sentenceCase);
1130     }
1131     std::string value = LocaleConfig::GetDisplayRegion(localeBuf.data(), displayLocaleBuf.data(), sentenceCase);
1132     if (value.length() == 0) {
1133         ErrorUtil::NapiThrow(env, I18N_NOT_VALID, throwError);
1134     }
1135     napi_value result = nullptr;
1136     status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result);
1137     if (status != napi_ok) {
1138         HiLog::Error(LABEL, "Failed to create string item");
1139         return nullptr;
1140     }
1141     return result;
1142 }
1143 
IsSuggested(napi_env env,napi_callback_info info)1144 napi_value I18nAddon::IsSuggested(napi_env env, napi_callback_info info)
1145 {
1146     return I18nAddon::IsSuggestedImpl(env, info, false);
1147 }
1148 
IsSuggestedWithError(napi_env env,napi_callback_info info)1149 napi_value I18nAddon::IsSuggestedWithError(napi_env env, napi_callback_info info)
1150 {
1151     return I18nAddon::IsSuggestedImpl(env, info, true);
1152 }
1153 
IsSuggestedImpl(napi_env env,napi_callback_info info,bool throwError)1154 napi_value I18nAddon::IsSuggestedImpl(napi_env env, napi_callback_info info, bool throwError)
1155 {
1156     // Need to get two parameters to check is suggested or not.
1157     size_t argc = 2;
1158     napi_value argv[2] = { 0 };
1159     napi_value thisVar = nullptr;
1160     void *data = nullptr;
1161     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1162     if (status != napi_ok) {
1163         return nullptr;
1164     }
1165     if (argv[0] == nullptr) {
1166         HiLog::Error(LABEL, "Missing parameter");
1167         ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, throwError);
1168         return nullptr;
1169     }
1170     size_t len = 0;
1171     napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len);
1172     std::vector<char> languageBuf(len + 1);
1173     status = napi_get_value_string_utf8(env, argv[0], languageBuf.data(), len + 1, &len);
1174     if (status != napi_ok) {
1175         HiLog::Error(LABEL, "Failed to get string item");
1176         ErrorUtil::NapiThrow(env, I18N_NOT_VALID, throwError);
1177         return nullptr;
1178     }
1179     bool isSuggested = false;
1180     if (CheckNapiValueType(env, argv[1])) {
1181         napi_get_value_string_utf8(env, argv[1], nullptr, 0, &len);
1182         std::vector<char> regionBuf(len + 1);
1183         status = napi_get_value_string_utf8(env, argv[1], regionBuf.data(), len + 1, &len);
1184         if (status != napi_ok) {
1185             HiLog::Error(LABEL, "Failed to get string item");
1186             ErrorUtil::NapiThrow(env, I18N_NOT_VALID, throwError);
1187             return nullptr;
1188         }
1189         isSuggested = LocaleConfig::IsSuggested(languageBuf.data(), regionBuf.data());
1190     } else {
1191         isSuggested = LocaleConfig::IsSuggested(languageBuf.data());
1192     }
1193     napi_value result = nullptr;
1194     status = napi_get_boolean(env, isSuggested, &result);
1195     if (status != napi_ok) {
1196         HiLog::Error(LABEL, "Create case first boolean value failed");
1197         return nullptr;
1198     }
1199     return result;
1200 }
1201 
SetSystemLanguage(napi_env env,napi_callback_info info)1202 napi_value I18nAddon::SetSystemLanguage(napi_env env, napi_callback_info info)
1203 {
1204     return I18nAddon::SetSystemLanguageImpl(env, info, false);
1205 }
1206 
SetSystemLanguageWithError(napi_env env,napi_callback_info info)1207 napi_value I18nAddon::SetSystemLanguageWithError(napi_env env, napi_callback_info info)
1208 {
1209     return I18nAddon::SetSystemLanguageImpl(env, info, true);
1210 }
1211 
SetSystemLanguageImpl(napi_env env,napi_callback_info info,bool throwError)1212 napi_value I18nAddon::SetSystemLanguageImpl(napi_env env, napi_callback_info info, bool throwError)
1213 {
1214     size_t argc = 1;
1215     napi_value argv[1] = { 0 };
1216     napi_value thisVar = nullptr;
1217     void *data = nullptr;
1218     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1219     if (status != napi_ok) {
1220         return nullptr;
1221     }
1222     if (argv[0] == nullptr) {
1223         HiLog::Error(LABEL, "Missing parameter");
1224         ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, throwError);
1225         return nullptr;
1226     }
1227     size_t len = 0;
1228     napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len);
1229     std::vector<char> languageBuf(len + 1);
1230     status = napi_get_value_string_utf8(env, argv[0], languageBuf.data(), len + 1, &len);
1231     if (status != napi_ok) {
1232         HiLog::Error(LABEL, "Failed to get string item");
1233         ErrorUtil::NapiThrow(env, I18N_NOT_VALID, throwError);
1234         return nullptr;
1235     }
1236     bool success = LocaleConfig::SetSystemLanguage(languageBuf.data());
1237     if (throwError) {
1238         if (!success) {
1239             ErrorUtil::NapiThrow(env, I18N_NO_PERMISSION, throwError);
1240         }
1241         return nullptr;
1242     }
1243     napi_value result = nullptr;
1244     status = napi_get_boolean(env, success, &result);
1245     if (status != napi_ok) {
1246         HiLog::Error(LABEL, "Create set system language boolean value failed");
1247         return nullptr;
1248     }
1249     return result;
1250 }
1251 
SetSystemRegion(napi_env env,napi_callback_info info)1252 napi_value I18nAddon::SetSystemRegion(napi_env env, napi_callback_info info)
1253 {
1254     return I18nAddon::SetSystemRegionImpl(env, info, false);
1255 }
1256 
SetSystemRegionWithError(napi_env env,napi_callback_info info)1257 napi_value I18nAddon::SetSystemRegionWithError(napi_env env, napi_callback_info info)
1258 {
1259     return I18nAddon::SetSystemRegionImpl(env, info, true);
1260 }
1261 
SetSystemRegionImpl(napi_env env,napi_callback_info info,bool throwError)1262 napi_value I18nAddon::SetSystemRegionImpl(napi_env env, napi_callback_info info, bool throwError)
1263 {
1264     size_t argc = 1;
1265     napi_value argv[1] = { 0 };
1266     napi_value thisVar = nullptr;
1267     void *data = nullptr;
1268     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1269     if (status != napi_ok) {
1270         return nullptr;
1271     }
1272     if (argv[0] == nullptr) {
1273         HiLog::Error(LABEL, "Missing parameter");
1274         ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, throwError);
1275         return nullptr;
1276     }
1277     size_t len = 0;
1278     napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len);
1279     std::vector<char> regionBuf(len + 1);
1280     status = napi_get_value_string_utf8(env, argv[0], regionBuf.data(), len + 1, &len);
1281     if (status != napi_ok) {
1282         HiLog::Error(LABEL, "Failed to get string item");
1283         ErrorUtil::NapiThrow(env, I18N_NOT_VALID, throwError);
1284         return nullptr;
1285     }
1286     bool success = LocaleConfig::SetSystemRegion(regionBuf.data());
1287     if (throwError) {
1288         if (!success) {
1289             ErrorUtil::NapiThrow(env, I18N_NO_PERMISSION, throwError);
1290         }
1291         return nullptr;
1292     }
1293     napi_value result = nullptr;
1294     status = napi_get_boolean(env, success, &result);
1295     if (status != napi_ok) {
1296         HiLog::Error(LABEL, "Create set system language boolean value failed");
1297         return nullptr;
1298     }
1299     return result;
1300 }
1301 
SetSystemLocale(napi_env env,napi_callback_info info)1302 napi_value I18nAddon::SetSystemLocale(napi_env env, napi_callback_info info)
1303 {
1304     return I18nAddon::SetSystemLocaleImpl(env, info, false);
1305 }
1306 
SetSystemLocaleWithError(napi_env env,napi_callback_info info)1307 napi_value I18nAddon::SetSystemLocaleWithError(napi_env env, napi_callback_info info)
1308 {
1309     return I18nAddon::SetSystemLocaleImpl(env, info, true);
1310 }
1311 
SetSystemLocaleImpl(napi_env env,napi_callback_info info,bool throwError)1312 napi_value I18nAddon::SetSystemLocaleImpl(napi_env env, napi_callback_info info, bool throwError)
1313 {
1314     size_t argc = 1;
1315     napi_value argv[1] = { 0 };
1316     napi_value thisVar = nullptr;
1317     void *data = nullptr;
1318     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1319     if (status != napi_ok) {
1320         return nullptr;
1321     }
1322     if (argv[0] == nullptr) {
1323         HiLog::Error(LABEL, "Missing parameter");
1324         ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, throwError);
1325         return nullptr;
1326     }
1327     size_t len = 0;
1328     napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len);
1329     std::vector<char> localeBuf(len + 1);
1330     status = napi_get_value_string_utf8(env, argv[0], localeBuf.data(), len + 1, &len);
1331     if (status != napi_ok) {
1332         HiLog::Error(LABEL, "Failed to get string item");
1333         ErrorUtil::NapiThrow(env, I18N_NOT_VALID, throwError);
1334         return nullptr;
1335     }
1336     bool success = LocaleConfig::SetSystemLocale(localeBuf.data());
1337     if (throwError) {
1338         if (!success) {
1339             ErrorUtil::NapiThrow(env, I18N_NO_PERMISSION, throwError);
1340         }
1341         return nullptr;
1342     }
1343     napi_value result = nullptr;
1344     status = napi_get_boolean(env, success, &result);
1345     if (status != napi_ok) {
1346         HiLog::Error(LABEL, "Create set system language boolean value failed");
1347         return nullptr;
1348     }
1349     return result;
1350 }
1351 
IsRTL(napi_env env,napi_callback_info info)1352 napi_value I18nAddon::IsRTL(napi_env env, napi_callback_info info)
1353 {
1354     size_t argc = 1;
1355     napi_value argv[1] = { 0 };
1356     napi_value thisVar = nullptr;
1357     void *data = nullptr;
1358     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1359     if (status != napi_ok) {
1360         return nullptr;
1361     }
1362     size_t len = 0;
1363     napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len);
1364     std::vector<char> localeBuf(len + 1);
1365     status = napi_get_value_string_utf8(env, argv[0], localeBuf.data(), len + 1, &len);
1366     if (status != napi_ok) {
1367         HiLog::Error(LABEL, "Failed to get string item");
1368         return nullptr;
1369     }
1370     bool isRTL = LocaleConfig::IsRTL(localeBuf.data());
1371     napi_value result = nullptr;
1372     status = napi_get_boolean(env, isRTL, &result);
1373     if (status != napi_ok) {
1374         HiLog::Error(LABEL, "IsRTL failed");
1375         return nullptr;
1376     }
1377     return result;
1378 }
1379 
InitPhoneNumberFormat(napi_env env,napi_value exports)1380 napi_value I18nAddon::InitPhoneNumberFormat(napi_env env, napi_value exports)
1381 {
1382     napi_status status = napi_ok;
1383     napi_property_descriptor properties[] = {
1384         DECLARE_NAPI_FUNCTION("isValidNumber", IsValidPhoneNumber),
1385         DECLARE_NAPI_FUNCTION("format", FormatPhoneNumber),
1386         DECLARE_NAPI_FUNCTION("getLocationName", GetLocationName)
1387     };
1388 
1389     napi_value constructor;
1390     status = napi_define_class(env, "PhoneNumberFormat", NAPI_AUTO_LENGTH, PhoneNumberFormatConstructor, nullptr,
1391                                sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor);
1392     if (status != napi_ok) {
1393         HiLog::Error(LABEL, "Define class failed when InitPhoneNumberFormat");
1394         return nullptr;
1395     }
1396 
1397     status = napi_set_named_property(env, exports, "PhoneNumberFormat", constructor);
1398     if (status != napi_ok) {
1399         HiLog::Error(LABEL, "Set property failed when InitPhoneNumberFormat");
1400         return nullptr;
1401     }
1402     return exports;
1403 }
1404 
GetOptionValue(napi_env env,napi_value options,const std::string & optionName,std::map<std::string,std::string> & map)1405 void GetOptionValue(napi_env env, napi_value options, const std::string &optionName,
1406                     std::map<std::string, std::string> &map)
1407 {
1408     napi_value optionValue = nullptr;
1409     napi_valuetype type = napi_undefined;
1410     napi_status status = napi_typeof(env, options, &type);
1411     if (status != napi_ok && type != napi_object) {
1412         HiLog::Error(LABEL, "Get option failed, option is not an object");
1413         return;
1414     }
1415     bool hasProperty = false;
1416     napi_status propStatus = napi_has_named_property(env, options, optionName.c_str(), &hasProperty);
1417     if (propStatus == napi_ok && hasProperty) {
1418         status = napi_get_named_property(env, options, optionName.c_str(), &optionValue);
1419         if (status == napi_ok) {
1420             size_t len = 0;
1421             napi_get_value_string_utf8(env, optionValue, nullptr, 0, &len);
1422             std::vector<char> optionBuf(len + 1);
1423             status = napi_get_value_string_utf8(env, optionValue, optionBuf.data(), len + 1, &len);
1424             if (status != napi_ok) {
1425                 return;
1426             }
1427             map.insert(make_pair(optionName, optionBuf.data()));
1428         }
1429     }
1430 }
1431 
PhoneNumberFormatConstructor(napi_env env,napi_callback_info info)1432 napi_value I18nAddon::PhoneNumberFormatConstructor(napi_env env, napi_callback_info info)
1433 {
1434     size_t argc = 2;
1435     napi_value argv[2] = { 0 };
1436     napi_value thisVar = nullptr;
1437     void *data = nullptr;
1438     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1439     if (status != napi_ok) {
1440         return nullptr;
1441     }
1442     napi_valuetype valueType = napi_valuetype::napi_undefined;
1443     napi_typeof(env, argv[0], &valueType);
1444     if (valueType != napi_valuetype::napi_string) {
1445         napi_throw_type_error(env, nullptr, "Parameter type does not match");
1446         return nullptr;
1447     }
1448     size_t len = 0;
1449     status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len);
1450     if (status != napi_ok) {
1451         HiLog::Error(LABEL, "Get country tag length failed");
1452         return nullptr;
1453     }
1454     std::vector<char> country (len + 1);
1455     status = napi_get_value_string_utf8(env, argv[0], country.data(), len + 1, &len);
1456     if (status != napi_ok) {
1457         HiLog::Error(LABEL, "Get country tag failed");
1458         return nullptr;
1459     }
1460     std::map<std::string, std::string> options;
1461     GetOptionValue(env, argv[1], "type", options);
1462     std::unique_ptr<I18nAddon> obj = nullptr;
1463     obj = std::make_unique<I18nAddon>();
1464     status = napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()),
1465                        I18nAddon::Destructor, nullptr, nullptr);
1466     if (status != napi_ok) {
1467         HiLog::Error(LABEL, "Wrap I18nAddon failed");
1468         return nullptr;
1469     }
1470     if (!obj->InitPhoneNumberFormatContext(env, info, country.data(), options)) {
1471         return nullptr;
1472     }
1473     obj.release();
1474     return thisVar;
1475 }
1476 
InitPhoneNumberFormatContext(napi_env env,napi_callback_info info,const std::string & country,const std::map<std::string,std::string> & options)1477 bool I18nAddon::InitPhoneNumberFormatContext(napi_env env, napi_callback_info info, const std::string &country,
1478                                              const std::map<std::string, std::string> &options)
1479 {
1480     napi_value global = nullptr;
1481     napi_status status = napi_get_global(env, &global);
1482     if (status != napi_ok) {
1483         HiLog::Error(LABEL, "Get global failed");
1484         return false;
1485     }
1486     env_ = env;
1487     phonenumberfmt_ = PhoneNumberFormat::CreateInstance(country, options);
1488 
1489     return phonenumberfmt_ != nullptr;
1490 }
1491 
IsValidPhoneNumber(napi_env env,napi_callback_info info)1492 napi_value I18nAddon::IsValidPhoneNumber(napi_env env, napi_callback_info info)
1493 {
1494     size_t argc = 1;
1495     napi_value argv[1] = { 0 };
1496     napi_value thisVar = nullptr;
1497     void *data = nullptr;
1498     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1499     napi_valuetype valueType = napi_valuetype::napi_undefined;
1500     napi_typeof(env, argv[0], &valueType);
1501     if (valueType != napi_valuetype::napi_string) {
1502         napi_throw_type_error(env, nullptr, "Parameter type does not match");
1503         return nullptr;
1504     }
1505 
1506     size_t len = 0;
1507     napi_status status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len);
1508     if (status != napi_ok) {
1509         HiLog::Error(LABEL, "Get phone number length failed");
1510         return nullptr;
1511     }
1512     std::vector<char> buf(len + 1);
1513     status = napi_get_value_string_utf8(env, argv[0], buf.data(), len + 1, &len);
1514     if (status != napi_ok) {
1515         HiLog::Error(LABEL, "Get phone number failed");
1516         return nullptr;
1517     }
1518 
1519     I18nAddon *obj = nullptr;
1520     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
1521     if (status != napi_ok || !obj || !obj->phonenumberfmt_) {
1522         HiLog::Error(LABEL, "GetPhoneNumberFormat object failed");
1523         return nullptr;
1524     }
1525 
1526     bool isValid = obj->phonenumberfmt_->isValidPhoneNumber(buf.data());
1527 
1528     napi_value result = nullptr;
1529     status = napi_get_boolean(env, isValid, &result);
1530     if (status != napi_ok) {
1531         HiLog::Error(LABEL, "Create boolean failed");
1532         return nullptr;
1533     }
1534 
1535     return result;
1536 }
1537 
GetLocationName(napi_env env,napi_callback_info info)1538 napi_value I18nAddon::GetLocationName(napi_env env, napi_callback_info info)
1539 {
1540     size_t argc = 2;
1541     napi_value argv[2] = {0, 0};
1542     napi_value thisVar = nullptr;
1543     void *data = nullptr;
1544     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1545 
1546     int32_t code = 0;
1547     std::string number = GetString(env, argv[0], code);
1548     if (code) {
1549         return nullptr;
1550     }
1551     std::string language = GetString(env, argv[1], code);
1552     if (code) {
1553         return nullptr;
1554     }
1555 
1556     I18nAddon *obj = nullptr;
1557     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
1558     if (status != napi_ok || !obj || !obj->phonenumberfmt_) {
1559         HiLog::Error(LABEL, "GetPhoneNumberFormat object failed");
1560         return nullptr;
1561     }
1562 
1563     std::string resStr = obj->phonenumberfmt_->getLocationName(number.data(), language.data());
1564     napi_value result = nullptr;
1565     status = napi_create_string_utf8(env, resStr.c_str(), NAPI_AUTO_LENGTH, &result);
1566     if (status != napi_ok) {
1567         HiLog::Error(LABEL, "Create result string failed");
1568         return nullptr;
1569     }
1570 
1571     return result;
1572 }
1573 
FormatPhoneNumber(napi_env env,napi_callback_info info)1574 napi_value I18nAddon::FormatPhoneNumber(napi_env env, napi_callback_info info)
1575 {
1576     size_t argc = 1;
1577     napi_value argv[1] = { 0 };
1578     napi_value thisVar = nullptr;
1579     void *data = nullptr;
1580     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1581     napi_valuetype valueType = napi_valuetype::napi_undefined;
1582     napi_typeof(env, argv[0], &valueType);
1583     if (valueType != napi_valuetype::napi_string) {
1584         napi_throw_type_error(env, nullptr, "Parameter type does not match");
1585         return nullptr;
1586     }
1587 
1588     size_t len = 0;
1589     napi_status status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len);
1590     if (status != napi_ok) {
1591         HiLog::Error(LABEL, "Get phone number length failed");
1592         return nullptr;
1593     }
1594     std::vector<char> buf(len + 1);
1595     status = napi_get_value_string_utf8(env, argv[0], buf.data(), len + 1, &len);
1596     if (status != napi_ok) {
1597         HiLog::Error(LABEL, "Get phone number failed");
1598         return nullptr;
1599     }
1600 
1601     I18nAddon *obj = nullptr;
1602     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
1603     if (status != napi_ok || !obj || !obj->phonenumberfmt_) {
1604         HiLog::Error(LABEL, "Get PhoneNumberFormat object failed");
1605         return nullptr;
1606     }
1607 
1608     std::string formattedPhoneNumber = obj->phonenumberfmt_->format(buf.data());
1609 
1610     napi_value result = nullptr;
1611     status = napi_create_string_utf8(env, formattedPhoneNumber.c_str(), NAPI_AUTO_LENGTH, &result);
1612     if (status != napi_ok) {
1613         HiLog::Error(LABEL, "Create format phone number failed");
1614         return nullptr;
1615     }
1616     return result;
1617 }
1618 
GetString(napi_env & env,napi_value & value,int32_t & code)1619 std::string I18nAddon::GetString(napi_env &env, napi_value &value, int32_t &code)
1620 {
1621     size_t len = 0;
1622     napi_status status = napi_get_value_string_utf8(env, value, nullptr, 0, &len);
1623     if (status != napi_ok) {
1624         HiLog::Error(LABEL, "Get string failed");
1625         code = 1;
1626         return "";
1627     }
1628     std::vector<char> buf(len + 1);
1629     status = napi_get_value_string_utf8(env, value, buf.data(), len + 1, &len);
1630     if (status != napi_ok) {
1631         HiLog::Error(LABEL, "Create string failed");
1632         code = 1;
1633         return "";
1634     }
1635     return buf.data();
1636 }
1637 
GetAddField(napi_env & env,napi_value & value,int32_t & code)1638 std::string I18nAddon::GetAddField(napi_env &env, napi_value &value, int32_t &code) {
1639     std::string field = GetString(env, value, code);
1640     if (code != 0) {
1641         HiLog::Error(LABEL, "can't get string from js array param.");
1642         ErrorUtil::NapiThrow(env, I18N_NOT_VALID, true);
1643         return field;
1644     }
1645     if (g_fieldsInFunctionAdd.find(field) == g_fieldsInFunctionAdd.end()) {
1646         code = 1;
1647         HiLog::Error(LABEL, "Parameter rangs do not match");
1648         ErrorUtil::NapiThrow(env, I18N_NOT_VALID, true);
1649         return field;
1650     }
1651     return field;
1652 }
1653 
InitI18nCalendar(napi_env env,napi_value exports)1654 napi_value I18nAddon::InitI18nCalendar(napi_env env, napi_value exports)
1655 {
1656     napi_status status = napi_ok;
1657     napi_property_descriptor properties[] = {
1658         DECLARE_NAPI_FUNCTION("setTime", SetTime),
1659         DECLARE_NAPI_FUNCTION("set", Set),
1660         DECLARE_NAPI_FUNCTION("getTimeZone", GetTimeZone),
1661         DECLARE_NAPI_FUNCTION("setTimeZone", SetTimeZone),
1662         DECLARE_NAPI_FUNCTION("getFirstDayOfWeek", GetFirstDayOfWeek),
1663         DECLARE_NAPI_FUNCTION("setFirstDayOfWeek", SetFirstDayOfWeek),
1664         DECLARE_NAPI_FUNCTION("getMinimalDaysInFirstWeek", GetMinimalDaysInFirstWeek),
1665         DECLARE_NAPI_FUNCTION("setMinimalDaysInFirstWeek", SetMinimalDaysInFirstWeek),
1666         DECLARE_NAPI_FUNCTION("get", Get),
1667         DECLARE_NAPI_FUNCTION("add", Add),
1668         DECLARE_NAPI_FUNCTION("getTimeInMillis", GetTimeInMillis),
1669         DECLARE_NAPI_FUNCTION("getDisplayName", GetDisplayName),
1670         DECLARE_NAPI_FUNCTION("isWeekend", IsWeekend)
1671     };
1672     napi_value constructor = nullptr;
1673     status = napi_define_class(env, "I18nCalendar", NAPI_AUTO_LENGTH, CalendarConstructor, nullptr,
1674         sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor);
1675     if (status != napi_ok) {
1676         HiLog::Error(LABEL, "Failed to define class at Init");
1677         return nullptr;
1678     }
1679     g_constructor = new (std::nothrow) napi_ref;
1680     if (!g_constructor) {
1681         HiLog::Error(LABEL, "Failed to create ref at init");
1682         return nullptr;
1683     }
1684     status = napi_create_reference(env, constructor, 1, g_constructor);
1685     if (status != napi_ok) {
1686         HiLog::Error(LABEL, "Failed to create reference at init");
1687         return nullptr;
1688     }
1689     return exports;
1690 }
1691 
CalendarConstructor(napi_env env,napi_callback_info info)1692 napi_value I18nAddon::CalendarConstructor(napi_env env, napi_callback_info info)
1693 {
1694     size_t argc = 2;
1695     napi_value argv[2] = { 0 };
1696     argv[0] = nullptr;
1697     argv[1] = nullptr;
1698     napi_value thisVar = nullptr;
1699     void *data = nullptr;
1700     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1701     if (status != napi_ok) {
1702         return nullptr;
1703     }
1704     napi_valuetype valueType = napi_valuetype::napi_undefined;
1705     napi_typeof(env, argv[0], &valueType);
1706     if (valueType != napi_valuetype::napi_string) {
1707         napi_throw_type_error(env, nullptr, "Parameter type does not match");
1708         return nullptr;
1709     }
1710     int32_t code = 0;
1711     std::string localeTag = GetString(env, argv[0], code);
1712     if (code) {
1713         return nullptr;
1714     }
1715     CalendarType type = GetCalendarType(env, argv[1]);
1716     std::unique_ptr<I18nAddon> obj = nullptr;
1717     obj = std::make_unique<I18nAddon>();
1718     status =
1719         napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()), I18nAddon::Destructor, nullptr, nullptr);
1720     if (status != napi_ok) {
1721         HiLog::Error(LABEL, "CalendarConstructor: Wrap II18nAddon failed");
1722         return nullptr;
1723     }
1724     if (!obj->InitCalendarContext(env, info, localeTag, type)) {
1725         return nullptr;
1726     }
1727     obj.release();
1728     return thisVar;
1729 }
1730 
GetCalendarType(napi_env env,napi_value value)1731 CalendarType I18nAddon::GetCalendarType(napi_env env, napi_value value)
1732 {
1733     CalendarType type = CalendarType::UNDEFINED;
1734     if (value != nullptr) {
1735         napi_valuetype valueType = napi_valuetype::napi_undefined;
1736         napi_typeof(env, value, &valueType);
1737         if (valueType != napi_valuetype::napi_string) {
1738             napi_throw_type_error(env, nullptr, "Parameter type does not match");
1739             return type;
1740         }
1741         int32_t code = 0;
1742         std::string calendarType = GetString(env, value, code);
1743         if (code) {
1744             return type;
1745         }
1746         if (g_typeMap.find(calendarType) != g_typeMap.end()) {
1747             type = g_typeMap[calendarType];
1748         }
1749     }
1750     return type;
1751 }
1752 
InitCalendarContext(napi_env env,napi_callback_info info,const std::string & localeTag,CalendarType type)1753 bool I18nAddon::InitCalendarContext(napi_env env, napi_callback_info info, const std::string &localeTag,
1754     CalendarType type)
1755 {
1756     calendar_ = std::make_unique<I18nCalendar>(localeTag, type);
1757     return calendar_ != nullptr;
1758 }
1759 
GetCalendar(napi_env env,napi_callback_info info)1760 napi_value I18nAddon::GetCalendar(napi_env env, napi_callback_info info)
1761 {
1762     size_t argc = 2; // retrieve 2 arguments
1763     napi_value argv[2] = { 0 };
1764     argv[0] = nullptr;
1765     argv[1] = nullptr;
1766     napi_value thisVar = nullptr;
1767     void *data = nullptr;
1768     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1769     napi_value constructor = nullptr;
1770     napi_status status = napi_get_reference_value(env, *g_constructor, &constructor);
1771     if (status != napi_ok) {
1772         HiLog::Error(LABEL, "Failed to create reference at GetCalendar");
1773         return nullptr;
1774     }
1775     if (!CheckNapiValueType(env, argv[1])) {
1776         status = napi_create_string_utf8(env, "", NAPI_AUTO_LENGTH, argv + 1);
1777         if (status != napi_ok) {
1778             return nullptr;
1779         }
1780     }
1781     napi_value result = nullptr;
1782     status = napi_new_instance(env, constructor, 2, argv, &result); // 2 arguments
1783     if (status != napi_ok) {
1784         HiLog::Error(LABEL, "Get calendar create instance failed");
1785         return nullptr;
1786     }
1787     return result;
1788 }
1789 
GetDate(napi_env env,napi_value value)1790 napi_value I18nAddon::GetDate(napi_env env, napi_value value)
1791 {
1792     if (!value) {
1793         return nullptr;
1794     }
1795     napi_value funcGetDateInfo = nullptr;
1796     napi_status status = napi_get_named_property(env, value, "valueOf", &funcGetDateInfo);
1797     if (status != napi_ok) {
1798         HiLog::Error(LABEL, "Get method valueOf failed");
1799         return nullptr;
1800     }
1801     napi_value ret_value = nullptr;
1802     status = napi_call_function(env, value, funcGetDateInfo, 0, nullptr, &ret_value);
1803     if (status != napi_ok) {
1804         HiLog::Error(LABEL, "Get milliseconds failed");
1805         return nullptr;
1806     }
1807     return ret_value;
1808 }
1809 
SetMilliseconds(napi_env env,napi_value value)1810 void I18nAddon::SetMilliseconds(napi_env env, napi_value value)
1811 {
1812     if (!value) {
1813         return;
1814     }
1815     double milliseconds = 0;
1816     napi_valuetype valueType = napi_valuetype::napi_undefined;
1817     napi_typeof(env, value, &valueType);
1818     if (valueType != napi_valuetype::napi_number) {
1819         napi_throw_type_error(env, nullptr, "Parameter type does not match");
1820         return;
1821     }
1822     napi_status status = napi_get_value_double(env, value, &milliseconds);
1823     if (status != napi_ok) {
1824         HiLog::Error(LABEL, "Retrieve milliseconds failed");
1825         return;
1826     }
1827     if (calendar_ != nullptr) {
1828         calendar_->SetTime(milliseconds);
1829     }
1830 }
1831 
Set(napi_env env,napi_callback_info info)1832 napi_value I18nAddon::Set(napi_env env, napi_callback_info info)
1833 {
1834     size_t argc = 6; // Set may have 6 arguments
1835     napi_value argv[6] = { 0 };
1836     for (size_t i = 0; i < argc; ++i) {
1837         argv[i] = nullptr;
1838     }
1839     napi_value thisVar = nullptr;
1840     void *data = nullptr;
1841     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1842     napi_valuetype valueType = napi_valuetype::napi_undefined;
1843     napi_status status = napi_ok;
1844     int32_t times[3] = { 0 }; // There are at least 3 arguments.
1845     for (int i = 0; i < 3; ++i) { // There are at least 3 arguments.
1846         napi_typeof(env, argv[i], &valueType);
1847         if (valueType != napi_valuetype::napi_number) {
1848             napi_throw_type_error(env, nullptr, "Parameter type does not match");
1849             return nullptr;
1850         }
1851         status = napi_get_value_int32(env, argv[i], times + i);
1852         if (status != napi_ok) {
1853             HiLog::Error(LABEL, "Retrieve time value failed");
1854             return nullptr;
1855         }
1856     }
1857     I18nAddon *obj = nullptr;
1858     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
1859     if (status != napi_ok || !obj || !obj->calendar_) {
1860         HiLog::Error(LABEL, "Get calendar object failed");
1861         return nullptr;
1862     }
1863     obj->calendar_->Set(times[0], times[1], times[2]); // 2 is the index of date
1864     obj->SetField(env, argv[3], UCalendarDateFields::UCAL_HOUR_OF_DAY); // 3 is the index of hour
1865     obj->SetField(env, argv[4], UCalendarDateFields::UCAL_MINUTE); // 4 is the index of minute
1866     obj->SetField(env, argv[5], UCalendarDateFields::UCAL_SECOND); // 5 is the index of second
1867     return nullptr;
1868 }
1869 
SetTime(napi_env env,napi_callback_info info)1870 napi_value I18nAddon::SetTime(napi_env env, napi_callback_info info)
1871 {
1872     size_t argc = 1;
1873     napi_value argv[1] = { 0 };
1874     argv[0] = nullptr;
1875     napi_value thisVar = nullptr;
1876     void *data = nullptr;
1877     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1878     if (!argv[0]) {
1879         return nullptr;
1880     }
1881     I18nAddon *obj = nullptr;
1882     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
1883     if (status != napi_ok || !obj || !obj->calendar_) {
1884         HiLog::Error(LABEL, "Get calendar object failed");
1885         return nullptr;
1886     }
1887     napi_valuetype type = napi_valuetype::napi_undefined;
1888     status = napi_typeof(env, argv[0], &type);
1889     if (status != napi_ok) {
1890         return nullptr;
1891     }
1892     if (type == napi_valuetype::napi_number) {
1893         obj->SetMilliseconds(env, argv[0]);
1894         return nullptr;
1895     } else {
1896         napi_value val = GetDate(env, argv[0]);
1897         if (!val) {
1898             return nullptr;
1899         }
1900         obj->SetMilliseconds(env, val);
1901         return nullptr;
1902     }
1903 }
1904 
SetField(napi_env env,napi_value value,UCalendarDateFields field)1905 void I18nAddon::SetField(napi_env env, napi_value value, UCalendarDateFields field)
1906 {
1907     if (!CheckNapiValueType(env, value)) {
1908         return;
1909     }
1910     int32_t val = 0;
1911     napi_valuetype valueType = napi_valuetype::napi_undefined;
1912     napi_typeof(env, value, &valueType);
1913     if (valueType != napi_valuetype::napi_number) {
1914         napi_throw_type_error(env, nullptr, "Parameter type does not match");
1915         return;
1916     }
1917     napi_status status = napi_get_value_int32(env, value, &val);
1918     if (status != napi_ok) {
1919         HiLog::Error(LABEL, "Retrieve field failed");
1920         return;
1921     }
1922     if (calendar_ != nullptr) {
1923         calendar_->Set(field, val);
1924     }
1925 }
1926 
SetTimeZone(napi_env env,napi_callback_info info)1927 napi_value I18nAddon::SetTimeZone(napi_env env, napi_callback_info info)
1928 {
1929     size_t argc = 1;
1930     napi_value argv[1] = { 0 };
1931     argv[0] = nullptr;
1932     napi_value thisVar = nullptr;
1933     void *data = nullptr;
1934     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1935     napi_valuetype valueType = napi_valuetype::napi_undefined;
1936     napi_typeof(env, argv[0], &valueType);
1937     if (valueType != napi_valuetype::napi_string) {
1938         napi_throw_type_error(env, nullptr, "Parameter type does not match");
1939         return nullptr;
1940     }
1941     size_t len = 0;
1942     napi_status status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len);
1943     if (status != napi_ok) {
1944         HiLog::Error(LABEL, "Get timezone length failed");
1945         return nullptr;
1946     }
1947     std::vector<char> buf(len + 1);
1948     status = napi_get_value_string_utf8(env, argv[0], buf.data(), len + 1, &len);
1949     if (status != napi_ok) {
1950         HiLog::Error(LABEL, "Get timezone failed");
1951         return nullptr;
1952     }
1953     std::string timezone(buf.data());
1954     I18nAddon *obj = nullptr;
1955     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
1956     if (status != napi_ok || !obj || !obj->calendar_) {
1957         HiLog::Error(LABEL, "Get calendar object failed");
1958         return nullptr;
1959     }
1960     obj->calendar_->SetTimeZone(timezone);
1961     return nullptr;
1962 }
1963 
GetTimeZone(napi_env env,napi_callback_info info)1964 napi_value I18nAddon::GetTimeZone(napi_env env, napi_callback_info info)
1965 {
1966     size_t argc = 0;
1967     napi_value *argv = nullptr;
1968     napi_value thisVar = nullptr;
1969     void *data = nullptr;
1970     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1971     I18nAddon *obj = nullptr;
1972     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
1973     if (status != napi_ok || !obj || !obj->calendar_) {
1974         HiLog::Error(LABEL, "Get calendar object failed");
1975         return nullptr;
1976     }
1977     std::string temp = obj->calendar_->GetTimeZone();
1978     napi_value result = nullptr;
1979     status = napi_create_string_utf8(env, temp.c_str(), NAPI_AUTO_LENGTH, &result);
1980     if (status != napi_ok) {
1981         HiLog::Error(LABEL, "Create timezone string failed");
1982         return nullptr;
1983     }
1984     return result;
1985 }
1986 
GetFirstDayOfWeek(napi_env env,napi_callback_info info)1987 napi_value I18nAddon::GetFirstDayOfWeek(napi_env env, napi_callback_info info)
1988 {
1989     size_t argc = 0;
1990     napi_value *argv = nullptr;
1991     napi_value thisVar = nullptr;
1992     void *data = nullptr;
1993     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1994     I18nAddon *obj = nullptr;
1995     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
1996     if (status != napi_ok || !obj || !obj->calendar_) {
1997         HiLog::Error(LABEL, "Get calendar object failed");
1998         return nullptr;
1999     }
2000     int32_t temp = obj->calendar_->GetFirstDayOfWeek();
2001     napi_value result = nullptr;
2002     status = napi_create_int32(env, temp, &result);
2003     if (status != napi_ok) {
2004         HiLog::Error(LABEL, "Create int32 failed");
2005         return nullptr;
2006     }
2007     return result;
2008 }
2009 
GetMinimalDaysInFirstWeek(napi_env env,napi_callback_info info)2010 napi_value I18nAddon::GetMinimalDaysInFirstWeek(napi_env env, napi_callback_info info)
2011 {
2012     size_t argc = 0;
2013     napi_value *argv = nullptr;
2014     napi_value thisVar = nullptr;
2015     void *data = nullptr;
2016     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2017     I18nAddon *obj = nullptr;
2018     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
2019     if (status != napi_ok || !obj || !obj->calendar_) {
2020         HiLog::Error(LABEL, "Get calendar object failed");
2021         return nullptr;
2022     }
2023     int32_t temp = obj->calendar_->GetMinimalDaysInFirstWeek();
2024     napi_value result = nullptr;
2025     status = napi_create_int32(env, temp, &result);
2026     if (status != napi_ok) {
2027         HiLog::Error(LABEL, "Create int32 failed");
2028         return nullptr;
2029     }
2030     return result;
2031 }
2032 
SetFirstDayOfWeek(napi_env env,napi_callback_info info)2033 napi_value I18nAddon::SetFirstDayOfWeek(napi_env env, napi_callback_info info)
2034 {
2035     size_t argc = 1;
2036     napi_value argv[1] = { 0 };
2037     argv[0] = nullptr;
2038     napi_value thisVar = nullptr;
2039     void *data = nullptr;
2040     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2041     napi_valuetype valueType = napi_valuetype::napi_undefined;
2042     napi_typeof(env, argv[0], &valueType);
2043     if (valueType != napi_valuetype::napi_number) {
2044         napi_throw_type_error(env, nullptr, "Parameter type does not match");
2045         return nullptr;
2046     }
2047     int32_t value = 0;
2048     napi_status status = napi_get_value_int32(env, argv[0], &value);
2049     if (status != napi_ok) {
2050         HiLog::Error(LABEL, "Get int32 failed");
2051         return nullptr;
2052     }
2053     I18nAddon *obj = nullptr;
2054     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
2055     if (status != napi_ok || !obj || !obj->calendar_) {
2056         HiLog::Error(LABEL, "Get calendar object failed");
2057         return nullptr;
2058     }
2059     obj->calendar_->SetFirstDayOfWeek(value);
2060     return nullptr;
2061 }
2062 
SetMinimalDaysInFirstWeek(napi_env env,napi_callback_info info)2063 napi_value I18nAddon::SetMinimalDaysInFirstWeek(napi_env env, napi_callback_info info)
2064 {
2065     size_t argc = 1;
2066     napi_value argv[1] = { 0 };
2067     argv[0] = nullptr;
2068     napi_value thisVar = nullptr;
2069     void *data = nullptr;
2070     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2071     napi_valuetype valueType = napi_valuetype::napi_undefined;
2072     napi_typeof(env, argv[0], &valueType);
2073     if (valueType != napi_valuetype::napi_number) {
2074         napi_throw_type_error(env, nullptr, "Parameter type does not match");
2075         return nullptr;
2076     }
2077     int32_t value = 0;
2078     napi_status status = napi_get_value_int32(env, argv[0], &value);
2079     if (status != napi_ok) {
2080         HiLog::Error(LABEL, "Get int32 failed");
2081         return nullptr;
2082     }
2083     I18nAddon *obj = nullptr;
2084     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
2085     if (status != napi_ok || !obj || !obj->calendar_) {
2086         HiLog::Error(LABEL, "Get calendar object failed");
2087         return nullptr;
2088     }
2089     obj->calendar_->SetMinimalDaysInFirstWeek(value);
2090     return nullptr;
2091 }
2092 
Get(napi_env env,napi_callback_info info)2093 napi_value I18nAddon::Get(napi_env env, napi_callback_info info)
2094 {
2095     size_t argc = 1;
2096     napi_value argv[1] = { 0 };
2097     argv[0] = nullptr;
2098     napi_value thisVar = nullptr;
2099     void *data = nullptr;
2100     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2101     napi_valuetype valueType = napi_valuetype::napi_undefined;
2102     napi_typeof(env, argv[0], &valueType);
2103     if (valueType != napi_valuetype::napi_string) {
2104         napi_throw_type_error(env, nullptr, "Parameter type does not match");
2105         return nullptr;
2106     }
2107     size_t len = 0;
2108     napi_status status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len);
2109     if (status != napi_ok) {
2110         HiLog::Error(LABEL, "Get field length failed");
2111         return nullptr;
2112     }
2113     std::vector<char> buf(len + 1);
2114     status = napi_get_value_string_utf8(env, argv[0], buf.data(), len + 1, &len);
2115     if (status != napi_ok) {
2116         HiLog::Error(LABEL, "Get field failed");
2117         return nullptr;
2118     }
2119     std::string field(buf.data());
2120     if (g_fieldsMap.find(field) == g_fieldsMap.end()) {
2121         HiLog::Error(LABEL, "Invalid field");
2122         return nullptr;
2123     }
2124     I18nAddon *obj = nullptr;
2125     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
2126     if (status != napi_ok || !obj || !obj->calendar_) {
2127         HiLog::Error(LABEL, "Get calendar object failed");
2128         return nullptr;
2129     }
2130     int32_t value = obj->calendar_->Get(g_fieldsMap[field]);
2131     napi_value result = nullptr;
2132     status = napi_create_int32(env, value, &result);
2133     if (status != napi_ok) {
2134         HiLog::Error(LABEL, "Create int32 failed");
2135         return nullptr;
2136     }
2137     return result;
2138 }
2139 
Add(napi_env env,napi_callback_info info)2140 napi_value I18nAddon::Add(napi_env env, napi_callback_info info) {
2141     size_t argc = 2;
2142     napi_value argv[2] = { 0 };
2143     napi_value thisVar = nullptr;
2144     void *data = nullptr;
2145     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2146     if (status != napi_ok) {
2147         HiLog::Error(LABEL, "can not obtain add function param.");
2148         ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, true);
2149         return nullptr;
2150     }
2151     napi_valuetype valueType = napi_valuetype::napi_undefined;
2152     napi_typeof(env, argv[0], &valueType);
2153     if (valueType != napi_valuetype::napi_string) {
2154         HiLog::Error(LABEL, "Parameter type does not match");
2155         ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, true);
2156         return nullptr;
2157     }
2158     int32_t code = 0;
2159     std::string field = GetAddField(env, argv[0], code);
2160     if (code) {
2161         return nullptr;
2162     }
2163     napi_typeof(env, argv[1], &valueType);
2164     if (valueType != napi_valuetype::napi_number) {
2165         HiLog::Error(LABEL, "Parameter type does not match");
2166         ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, true);
2167         return nullptr;
2168     }
2169     int32_t amount;
2170     status = napi_get_value_int32(env, argv[1], &amount);
2171     if (status != napi_ok) {
2172         HiLog::Error(LABEL, "can not obtain add function param.");
2173         ErrorUtil::NapiThrow(env, I18N_NOT_VALID, true);
2174         return nullptr;
2175     }
2176     I18nAddon *obj = nullptr;
2177     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
2178     if (status != napi_ok || !obj || !obj->calendar_) {
2179         HiLog::Error(LABEL, "Get calendar object failed");
2180         return nullptr;
2181     }
2182     obj->calendar_->Add(g_fieldsMap[field], amount);
2183     return nullptr;
2184 }
2185 
GetTimeInMillis(napi_env env,napi_callback_info info)2186 napi_value I18nAddon::GetTimeInMillis(napi_env env, napi_callback_info info) {
2187     bool flag = true;
2188     size_t argc = 0;
2189     napi_value *argv = nullptr;
2190     napi_value thisVar = nullptr;
2191     void *data = nullptr;
2192     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2193     I18nAddon *obj = nullptr;
2194     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
2195     if (status != napi_ok || !obj || !obj->calendar_) {
2196         HiLog::Error(LABEL, "Get calendar object failed");
2197         flag = false;
2198     }
2199     UDate temp = 0;
2200     if (flag) {
2201         temp = obj->calendar_->GetTimeInMillis();
2202     }
2203     napi_value result = nullptr;
2204     status = napi_create_double(env, temp, &result);
2205     if (status != napi_ok) {
2206         HiLog::Error(LABEL, "Create UDate failed");
2207         napi_create_double(env, 0, &result);
2208     }
2209     return result;
2210 }
2211 
IsWeekend(napi_env env,napi_callback_info info)2212 napi_value I18nAddon::IsWeekend(napi_env env, napi_callback_info info)
2213 {
2214     size_t argc = 1;
2215     napi_value argv[1] = { 0 };
2216     argv[0] = nullptr;
2217     napi_value thisVar = nullptr;
2218     void *data = nullptr;
2219     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2220     I18nAddon *obj = nullptr;
2221     bool isWeekEnd = false;
2222     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
2223     do {
2224         if (status != napi_ok || !obj || !obj->calendar_) {
2225             HiLog::Error(LABEL, "Get calendar object failed");
2226             break;
2227         }
2228         if (!argv[0]) {
2229             isWeekEnd = obj->calendar_->IsWeekend();
2230         } else {
2231             napi_value funcGetDateInfo = nullptr;
2232             status = napi_get_named_property(env, argv[0], "valueOf", &funcGetDateInfo);
2233             if (status != napi_ok) {
2234                 HiLog::Error(LABEL, "Get method now failed");
2235                 break;
2236             }
2237             napi_value value = nullptr;
2238             status = napi_call_function(env, argv[0], funcGetDateInfo, 0, nullptr, &value);
2239             if (status != napi_ok) {
2240                 HiLog::Error(LABEL, "Get milliseconds failed");
2241                 break;
2242             }
2243             double milliseconds = 0;
2244             status = napi_get_value_double(env, value, &milliseconds);
2245             if (status != napi_ok) {
2246                 HiLog::Error(LABEL, "Retrieve milliseconds failed");
2247                 break;
2248             }
2249             UErrorCode error = U_ZERO_ERROR;
2250             isWeekEnd = obj->calendar_->IsWeekend(milliseconds, error);
2251         }
2252     } while (false);
2253     napi_value result = nullptr;
2254     status = napi_get_boolean(env, isWeekEnd, &result);
2255     if (status != napi_ok) {
2256         HiLog::Error(LABEL, "Create boolean failed");
2257         return nullptr;
2258     }
2259     return result;
2260 }
2261 
GetDisplayName(napi_env env,napi_callback_info info)2262 napi_value I18nAddon::GetDisplayName(napi_env env, napi_callback_info info)
2263 {
2264     size_t argc = 1;
2265     napi_value argv[1] = { 0 };
2266     argv[0] = nullptr;
2267     napi_value thisVar = nullptr;
2268     void *data = nullptr;
2269     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2270     napi_valuetype valueType = napi_valuetype::napi_undefined;
2271     napi_typeof(env, argv[0], &valueType);
2272     if (valueType != napi_valuetype::napi_string) {
2273         napi_throw_type_error(env, nullptr, "Parameter type does not match");
2274         return nullptr;
2275     }
2276     int32_t code = 0;
2277     std::string localeTag = GetString(env, argv[0], code);
2278     if (code) {
2279         return nullptr;
2280     }
2281     I18nAddon *obj = nullptr;
2282     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
2283     if (status != napi_ok || !obj || !obj->calendar_) {
2284         HiLog::Error(LABEL, "Get calendar object failed");
2285         return nullptr;
2286     }
2287     if (!obj->calendar_) {
2288         return nullptr;
2289     }
2290     std::string name = obj->calendar_->GetDisplayName(localeTag);
2291     napi_value result = nullptr;
2292     status = napi_create_string_utf8(env, name.c_str(), NAPI_AUTO_LENGTH, &result);
2293     if (status != napi_ok) {
2294         HiLog::Error(LABEL, "Create calendar name string failed");
2295         return nullptr;
2296     }
2297     return result;
2298 }
2299 
InitIndexUtil(napi_env env,napi_value exports)2300 napi_value I18nAddon::InitIndexUtil(napi_env env, napi_value exports)
2301 {
2302     napi_property_descriptor properties[] = {
2303         DECLARE_NAPI_FUNCTION("getIndexList", GetIndexList),
2304         DECLARE_NAPI_FUNCTION("addLocale", AddLocale),
2305         DECLARE_NAPI_FUNCTION("getIndex", GetIndex)
2306     };
2307 
2308     napi_value constructor = nullptr;
2309     napi_status status = napi_define_class(env, "IndexUtil", NAPI_AUTO_LENGTH, IndexUtilConstructor, nullptr,
2310         sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor);
2311     if (status != napi_ok) {
2312         HiLog::Error(LABEL, "Define class failed when InitPhoneNumberFormat");
2313         return nullptr;
2314     }
2315 
2316     status = napi_create_reference(env, constructor, 1, &g_indexUtilConstructor);
2317     if (status != napi_ok) {
2318         HiLog::Error(LABEL, "Failed to create reference at init");
2319         return nullptr;
2320     }
2321     return exports;
2322 }
2323 
BreakIteratorConstructor(napi_env env,napi_callback_info info)2324 napi_value I18nAddon::BreakIteratorConstructor(napi_env env, napi_callback_info info)
2325 {
2326     size_t argc = 1;
2327     napi_value argv[1] = { nullptr };
2328     napi_value thisVar = nullptr;
2329     void *data = nullptr;
2330     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2331     if (status != napi_ok) {
2332         return nullptr;
2333     }
2334     napi_valuetype valueType = napi_valuetype::napi_undefined;
2335     napi_typeof(env, argv[0], &valueType);
2336     if (valueType != napi_valuetype::napi_string) {
2337         napi_throw_type_error(env, nullptr, "Parameter type does not match");
2338         return nullptr;
2339     }
2340     int32_t code = 0;
2341     std::string localeTag = GetString(env, argv[0], code);
2342     if (code) {
2343         return nullptr;
2344     }
2345     std::unique_ptr<I18nAddon> obj = nullptr;
2346     obj = std::make_unique<I18nAddon>();
2347     status =
2348         napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()), I18nAddon::Destructor, nullptr, nullptr);
2349     if (status != napi_ok) {
2350         HiLog::Error(LABEL, "BreakIteratorConstructor: Wrap II18nAddon failed");
2351         return nullptr;
2352     }
2353     obj->brkiter_ = std::make_unique<I18nBreakIterator>(localeTag);
2354     if (!obj->brkiter_) {
2355         HiLog::Error(LABEL, "Wrap BreakIterator failed");
2356         return nullptr;
2357     }
2358     obj.release();
2359     return thisVar;
2360 }
2361 
InitBreakIterator(napi_env env,napi_value exports)2362 napi_value I18nAddon::InitBreakIterator(napi_env env, napi_value exports)
2363 {
2364     napi_status status = napi_ok;
2365     napi_property_descriptor properties[] = {
2366         DECLARE_NAPI_FUNCTION("current", Current),
2367         DECLARE_NAPI_FUNCTION("first", First),
2368         DECLARE_NAPI_FUNCTION("last", Last),
2369         DECLARE_NAPI_FUNCTION("next", Next),
2370         DECLARE_NAPI_FUNCTION("previous", Previous),
2371         DECLARE_NAPI_FUNCTION("setLineBreakText", SetText),
2372         DECLARE_NAPI_FUNCTION("following", Following),
2373         DECLARE_NAPI_FUNCTION("getLineBreakText", GetText),
2374         DECLARE_NAPI_FUNCTION("isBoundary", IsBoundary),
2375     };
2376     napi_value constructor = nullptr;
2377     status = napi_define_class(env, "BreakIterator", NAPI_AUTO_LENGTH, BreakIteratorConstructor, nullptr,
2378         sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor);
2379     if (status != napi_ok) {
2380         HiLog::Error(LABEL, "Failed to define class BreakIterator at Init");
2381         return nullptr;
2382     }
2383     g_brkConstructor = new (std::nothrow) napi_ref;
2384     if (!g_brkConstructor) {
2385         HiLog::Error(LABEL, "Failed to create brkiterator ref at init");
2386         return nullptr;
2387     }
2388     status = napi_create_reference(env, constructor, 1, g_brkConstructor);
2389     if (status != napi_ok) {
2390         HiLog::Error(LABEL, "Failed to create reference g_brkConstructor at init");
2391         return nullptr;
2392     }
2393     return exports;
2394 }
2395 
GetLineInstance(napi_env env,napi_callback_info info)2396 napi_value I18nAddon::GetLineInstance(napi_env env, napi_callback_info info)
2397 {
2398     size_t argc = 1;
2399     napi_value argv[1] = { nullptr };
2400     napi_value thisVar = nullptr;
2401     void *data = nullptr;
2402     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2403     napi_value constructor = nullptr;
2404     napi_status status = napi_get_reference_value(env, *g_brkConstructor, &constructor);
2405     if (status != napi_ok) {
2406         HiLog::Error(LABEL, "Failed to create reference at GetLineInstance");
2407         return nullptr;
2408     }
2409     if (!argv[0]) {
2410         return nullptr;
2411     }
2412     napi_value result = nullptr;
2413     status = napi_new_instance(env, constructor, 1, argv, &result); // 1 arguments
2414     if (status != napi_ok) {
2415         HiLog::Error(LABEL, "GetLineInstance create instance failed");
2416         return nullptr;
2417     }
2418     return result;
2419 }
2420 
Current(napi_env env,napi_callback_info info)2421 napi_value I18nAddon::Current(napi_env env, napi_callback_info info)
2422 {
2423     size_t argc = 0;
2424     napi_value *argv = nullptr;
2425     napi_value thisVar = nullptr;
2426     void *data = nullptr;
2427     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2428     I18nAddon *obj = nullptr;
2429     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
2430     if (status != napi_ok || !obj || !obj->brkiter_) {
2431         HiLog::Error(LABEL, "Get BreakIterator object failed");
2432         return nullptr;
2433     }
2434     int value = obj->brkiter_->Current();
2435     napi_value result = nullptr;
2436     status = napi_create_int32(env, value, &result);
2437     if (status != napi_ok) {
2438         HiLog::Error(LABEL, "Create int32_t value failed");
2439         return nullptr;
2440     }
2441     return result;
2442 }
2443 
First(napi_env env,napi_callback_info info)2444 napi_value I18nAddon::First(napi_env env, napi_callback_info info)
2445 {
2446     size_t argc = 0;
2447     napi_value *argv = nullptr;
2448     napi_value thisVar = nullptr;
2449     void *data = nullptr;
2450     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2451     I18nAddon *obj = nullptr;
2452     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
2453     if (status != napi_ok || !obj || !obj->brkiter_) {
2454         HiLog::Error(LABEL, "Get BreakIterator object failed");
2455         return nullptr;
2456     }
2457     int value = obj->brkiter_->First();
2458     napi_value result = nullptr;
2459     status = napi_create_int32(env, value, &result);
2460     if (status != napi_ok) {
2461         HiLog::Error(LABEL, "Create int32_t value failed");
2462         return nullptr;
2463     }
2464     return result;
2465 }
2466 
Last(napi_env env,napi_callback_info info)2467 napi_value I18nAddon::Last(napi_env env, napi_callback_info info)
2468 {
2469     size_t argc = 0;
2470     napi_value *argv = nullptr;
2471     napi_value thisVar = nullptr;
2472     void *data = nullptr;
2473     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2474     I18nAddon *obj = nullptr;
2475     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
2476     if (status != napi_ok || !obj || !obj->brkiter_) {
2477         HiLog::Error(LABEL, "Get BreakIterator object failed");
2478         return nullptr;
2479     }
2480     int value = obj->brkiter_->Last();
2481     napi_value result = nullptr;
2482     status = napi_create_int32(env, value, &result);
2483     if (status != napi_ok) {
2484         HiLog::Error(LABEL, "Create int32_t value failed");
2485         return nullptr;
2486     }
2487     return result;
2488 }
2489 
Previous(napi_env env,napi_callback_info info)2490 napi_value I18nAddon::Previous(napi_env env, napi_callback_info info)
2491 {
2492     size_t argc = 0;
2493     napi_value *argv = nullptr;
2494     napi_value thisVar = nullptr;
2495     void *data = nullptr;
2496     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2497     I18nAddon *obj = nullptr;
2498     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
2499     if (status != napi_ok || !obj || !obj->brkiter_) {
2500         HiLog::Error(LABEL, "Get BreakIterator object failed");
2501         return nullptr;
2502     }
2503     int value = obj->brkiter_->Previous();
2504     napi_value result = nullptr;
2505     status = napi_create_int32(env, value, &result);
2506     if (status != napi_ok) {
2507         HiLog::Error(LABEL, "Create int32_t value failed");
2508         return nullptr;
2509     }
2510     return result;
2511 }
2512 
Next(napi_env env,napi_callback_info info)2513 napi_value I18nAddon::Next(napi_env env, napi_callback_info info)
2514 {
2515     size_t argc = 1;
2516     napi_value argv[1] = { nullptr };
2517     napi_value thisVar = nullptr;
2518     void *data = nullptr;
2519     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2520     I18nAddon *obj = nullptr;
2521     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
2522     if (status != napi_ok || !obj || !obj->brkiter_) {
2523         HiLog::Error(LABEL, "Get BreakIterator object failed");
2524         return nullptr;
2525     }
2526     int value = 1;
2527     if (CheckNapiValueType(env, argv[0])) {
2528         napi_valuetype valueType = napi_valuetype::napi_undefined;
2529         napi_typeof(env, argv[0], &valueType);
2530         if (valueType != napi_valuetype::napi_number) {
2531             napi_throw_type_error(env, nullptr, "Parameter type does not match");
2532             return nullptr;
2533         }
2534         status = napi_get_value_int32(env, argv[0], &value);
2535         if (status != napi_ok) {
2536             HiLog::Error(LABEL, "Retrieve next value failed");
2537             return nullptr;
2538         }
2539     }
2540     value = obj->brkiter_->Next(value);
2541     napi_value result = nullptr;
2542     status = napi_create_int32(env, value, &result);
2543     if (status != napi_ok) {
2544         HiLog::Error(LABEL, "Create int32_t value failed");
2545         return nullptr;
2546     }
2547     return result;
2548 }
2549 
SetText(napi_env env,napi_callback_info info)2550 napi_value I18nAddon::SetText(napi_env env, napi_callback_info info)
2551 {
2552     size_t argc = 1;
2553     napi_value argv[1] = { nullptr };
2554     napi_value thisVar = nullptr;
2555     void *data = nullptr;
2556     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2557     I18nAddon *obj = nullptr;
2558     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
2559     if (status != napi_ok || !obj || !obj->brkiter_) {
2560         HiLog::Error(LABEL, "Get BreakIterator object failed");
2561         return nullptr;
2562     }
2563     if (!argv[0]) {
2564         return nullptr;
2565     }
2566     napi_valuetype valueType = napi_valuetype::napi_undefined;
2567     napi_typeof(env, argv[0], &valueType);
2568     if (valueType != napi_valuetype::napi_string) {
2569         napi_throw_type_error(env, nullptr, "Parameter type does not match");
2570         return nullptr;
2571     }
2572     size_t len = 0;
2573     status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len);
2574     if (status != napi_ok) {
2575         HiLog::Error(LABEL, "Get field length failed");
2576         return nullptr;
2577     }
2578     std::vector<char> buf(len + 1);
2579     status = napi_get_value_string_utf8(env, argv[0], buf.data(), len + 1, &len);
2580     if (status != napi_ok) {
2581         HiLog::Error(LABEL, "Get string value failed");
2582         return nullptr;
2583     }
2584     obj->brkiter_->SetText(buf.data());
2585     return nullptr;
2586 }
2587 
GetText(napi_env env,napi_callback_info info)2588 napi_value I18nAddon::GetText(napi_env env, napi_callback_info info)
2589 {
2590     size_t argc = 0;
2591     napi_value *argv = nullptr;
2592     napi_value thisVar = nullptr;
2593     void *data = nullptr;
2594     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2595     I18nAddon *obj = nullptr;
2596     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
2597     if (status != napi_ok || !obj || !obj->brkiter_) {
2598         HiLog::Error(LABEL, "Get BreakIterator object failed");
2599         return nullptr;
2600     }
2601     napi_value value = nullptr;
2602     std::string temp;
2603     obj->brkiter_->GetText(temp);
2604     status = napi_create_string_utf8(env, temp.c_str(), NAPI_AUTO_LENGTH, &value);
2605     if (status != napi_ok) {
2606         HiLog::Error(LABEL, "Get field length failed");
2607         return nullptr;
2608     }
2609     return value;
2610 }
2611 
Following(napi_env env,napi_callback_info info)2612 napi_value I18nAddon::Following(napi_env env, napi_callback_info info)
2613 {
2614     size_t argc = 1;
2615     napi_value argv[1] = { nullptr };
2616     napi_value thisVar = nullptr;
2617     void *data = nullptr;
2618     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2619     I18nAddon *obj = nullptr;
2620     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
2621     if (status != napi_ok || !obj || !obj->brkiter_) {
2622         HiLog::Error(LABEL, "Get BreakIterator object failed");
2623         return nullptr;
2624     }
2625     if (!argv[0]) {
2626         return nullptr;
2627     }
2628     napi_valuetype valueType = napi_valuetype::napi_undefined;
2629     napi_typeof(env, argv[0], &valueType);
2630     if (valueType != napi_valuetype::napi_number) {
2631         napi_throw_type_error(env, nullptr, "Parameter type does not match");
2632         return nullptr;
2633     }
2634     int value;
2635     status = napi_get_value_int32(env, argv[0], &value);
2636     if (status != napi_ok) {
2637         HiLog::Error(LABEL, "Retrieve following value failed");
2638         return nullptr;
2639     }
2640     value = obj->brkiter_->Following(value);
2641     napi_value result = nullptr;
2642     status = napi_create_int32(env, value, &result);
2643     if (status != napi_ok) {
2644         HiLog::Error(LABEL, "Create int32_t value failed");
2645         return nullptr;
2646     }
2647     return result;
2648 }
2649 
IsBoundary(napi_env env,napi_callback_info info)2650 napi_value I18nAddon::IsBoundary(napi_env env, napi_callback_info info)
2651 {
2652     size_t argc = 1;
2653     napi_value argv[1] = { nullptr };
2654     napi_value thisVar = nullptr;
2655     void *data = nullptr;
2656     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2657     I18nAddon *obj = nullptr;
2658     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
2659     if (status != napi_ok || !obj || !obj->brkiter_) {
2660         HiLog::Error(LABEL, "Get BreakIterator object failed");
2661         return nullptr;
2662     }
2663     if (!argv[0]) {
2664         return nullptr;
2665     }
2666     napi_valuetype valueType = napi_valuetype::napi_undefined;
2667     int value;
2668     napi_typeof(env, argv[0], &valueType);
2669     if (valueType != napi_valuetype::napi_number) {
2670         napi_throw_type_error(env, nullptr, "Parameter type does not match");
2671         return nullptr;
2672     }
2673     status = napi_get_value_int32(env, argv[0], &value);
2674     if (status != napi_ok) {
2675         HiLog::Error(LABEL, "Retrieve following value failed");
2676         return nullptr;
2677     }
2678     bool boundary = obj->brkiter_->IsBoundary(value);
2679     napi_value result = nullptr;
2680     status = napi_get_boolean(env, boundary, &result);
2681     if (status != napi_ok) {
2682         HiLog::Error(LABEL, "Create boolean failed");
2683         return nullptr;
2684     }
2685     return result;
2686 }
2687 
IndexUtilConstructor(napi_env env,napi_callback_info info)2688 napi_value I18nAddon::IndexUtilConstructor(napi_env env, napi_callback_info info)
2689 {
2690     size_t argc = 1;
2691     napi_value argv[1] = { 0 };
2692     napi_value thisVar = nullptr;
2693     void *data = nullptr;
2694     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2695     if (status != napi_ok) {
2696         return nullptr;
2697     }
2698     std::string localeTag = "";
2699     if (argv[0] != nullptr) {
2700         napi_valuetype valueType = napi_valuetype::napi_undefined;
2701         napi_typeof(env, argv[0], &valueType);
2702         if (valueType != napi_valuetype::napi_string) {
2703             napi_throw_type_error(env, nullptr, "Parameter type does not match");
2704             return nullptr;
2705         }
2706         size_t len = 0;
2707         status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len);
2708         if (status != napi_ok) {
2709             HiLog::Error(LABEL, "Get locale length failed");
2710             return nullptr;
2711         }
2712         std::vector<char> localeBuf(len + 1);
2713         status = napi_get_value_string_utf8(env, argv[0], localeBuf.data(), len + 1, &len);
2714         if (status != napi_ok) {
2715             HiLog::Error(LABEL, "Get locale failed");
2716             return nullptr;
2717         }
2718         localeTag = localeBuf.data();
2719     }
2720     std::unique_ptr<I18nAddon> obj = nullptr;
2721     obj = std::make_unique<I18nAddon>();
2722     status =
2723         napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()), I18nAddon::Destructor, nullptr, nullptr);
2724     if (status != napi_ok) {
2725         HiLog::Error(LABEL, "IndexUtilConstructor: Wrap II18nAddon failed");
2726         return nullptr;
2727     }
2728     if (!obj->InitIndexUtilContext(env, info, localeTag)) {
2729         return nullptr;
2730     }
2731     obj.release();
2732     return thisVar;
2733 }
2734 
InitIndexUtilContext(napi_env env,napi_callback_info info,const std::string & localeTag)2735 bool I18nAddon::InitIndexUtilContext(napi_env env, napi_callback_info info, const std::string &localeTag)
2736 {
2737     napi_value global = nullptr;
2738     napi_status status = napi_get_global(env, &global);
2739     if (status != napi_ok) {
2740         HiLog::Error(LABEL, "Get global failed");
2741         return false;
2742     }
2743     env_ = env;
2744     indexUtil_ = std::make_unique<IndexUtil>(localeTag);
2745     return indexUtil_ != nullptr;
2746 }
2747 
GetIndexUtil(napi_env env,napi_callback_info info)2748 napi_value I18nAddon::GetIndexUtil(napi_env env, napi_callback_info info)
2749 {
2750     size_t argc = 1;
2751     napi_value argv[1] = { 0 };
2752     napi_value thisVar = nullptr;
2753     void *data = nullptr;
2754     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2755     napi_value constructor = nullptr;
2756     napi_status status = napi_get_reference_value(env, g_indexUtilConstructor, &constructor);
2757     if (status != napi_ok) {
2758         HiLog::Error(LABEL, "Failed to create reference at GetIndexUtil");
2759         return nullptr;
2760     }
2761     napi_value result = nullptr;
2762     if (!CheckNapiValueType(env, argv[0])) {
2763         status = napi_new_instance(env, constructor, 0, argv, &result);
2764     } else {
2765         status = napi_new_instance(env, constructor, 1, argv, &result);
2766     }
2767     if (status != napi_ok) {
2768         HiLog::Error(LABEL, "Get calendar create instance failed");
2769         return nullptr;
2770     }
2771     return result;
2772 }
2773 
GetIndexList(napi_env env,napi_callback_info info)2774 napi_value I18nAddon::GetIndexList(napi_env env, napi_callback_info info)
2775 {
2776     size_t argc = 0;
2777     napi_value argv[0];
2778     napi_value thisVar = nullptr;
2779     void *data = nullptr;
2780     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2781 
2782     I18nAddon *obj = nullptr;
2783     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
2784     if (status != napi_ok || !obj || !obj->indexUtil_) {
2785         HiLog::Error(LABEL, "GetPhoneNumberFormat object failed");
2786         return nullptr;
2787     }
2788 
2789     std::vector<std::string> indexList = obj->indexUtil_->GetIndexList();
2790     napi_value result = nullptr;
2791     status = napi_create_array_with_length(env, indexList.size(), &result);
2792     if (status != napi_ok) {
2793         HiLog::Error(LABEL, "Failed to create array");
2794         return nullptr;
2795     }
2796     for (size_t i = 0; i < indexList.size(); i++) {
2797         napi_value element = nullptr;
2798         status = napi_create_string_utf8(env, indexList[i].c_str(), NAPI_AUTO_LENGTH, &element);
2799         if (status != napi_ok) {
2800             HiLog::Error(LABEL, "Failed to create string item");
2801             return nullptr;
2802         }
2803         status = napi_set_element(env, result, i, element);
2804         if (status != napi_ok) {
2805             HiLog::Error(LABEL, "Failed to set array item");
2806             return nullptr;
2807         }
2808     }
2809     return result;
2810 }
2811 
AddLocale(napi_env env,napi_callback_info info)2812 napi_value I18nAddon::AddLocale(napi_env env, napi_callback_info info)
2813 {
2814     size_t argc = 1;
2815     napi_value argv[1] = { 0 };
2816     napi_value thisVar = nullptr;
2817     void *data = nullptr;
2818     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2819     napi_valuetype valueType = napi_valuetype::napi_undefined;
2820     napi_typeof(env, argv[0], &valueType);
2821     if (valueType != napi_valuetype::napi_string) {
2822         napi_throw_type_error(env, nullptr, "Parameter type does not match");
2823         return nullptr;
2824     }
2825     size_t len = 0;
2826     napi_status status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len);
2827     if (status != napi_ok) {
2828         HiLog::Error(LABEL, "Get locale length failed");
2829         return nullptr;
2830     }
2831     std::vector<char> buf(len + 1);
2832     status = napi_get_value_string_utf8(env, argv[0], buf.data(), len + 1, &len);
2833     if (status != napi_ok) {
2834         HiLog::Error(LABEL, "Get locale failed");
2835         return nullptr;
2836     }
2837     I18nAddon *obj = nullptr;
2838     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
2839     if (status != napi_ok || !obj || !obj->indexUtil_) {
2840         HiLog::Error(LABEL, "Get IndexUtil object failed");
2841         return nullptr;
2842     }
2843     obj->indexUtil_->AddLocale(buf.data());
2844     return nullptr;
2845 }
2846 
GetIndex(napi_env env,napi_callback_info info)2847 napi_value I18nAddon::GetIndex(napi_env env, napi_callback_info info)
2848 {
2849     size_t argc = 1;
2850     napi_value argv[1] = { 0 };
2851     napi_value thisVar = nullptr;
2852     void *data = nullptr;
2853     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2854     napi_valuetype valueType = napi_valuetype::napi_undefined;
2855     napi_typeof(env, argv[0], &valueType);
2856     if (valueType != napi_valuetype::napi_string) {
2857         napi_throw_type_error(env, nullptr, "Parameter type does not match");
2858         return nullptr;
2859     }
2860     size_t len = 0;
2861     napi_status status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len);
2862     if (status != napi_ok) {
2863         HiLog::Error(LABEL, "Get String length failed");
2864         return nullptr;
2865     }
2866     std::vector<char> buf(len + 1);
2867     status = napi_get_value_string_utf8(env, argv[0], buf.data(), len + 1, &len);
2868     if (status != napi_ok) {
2869         HiLog::Error(LABEL, "Get String failed");
2870         return nullptr;
2871     }
2872     I18nAddon *obj = nullptr;
2873     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
2874     if (status != napi_ok || !obj || !obj->indexUtil_) {
2875         HiLog::Error(LABEL, "Get IndexUtil object failed");
2876         return nullptr;
2877     }
2878     std::string index = obj->indexUtil_->GetIndex(buf.data());
2879     napi_value result = nullptr;
2880     status = napi_create_string_utf8(env, index.c_str(), NAPI_AUTO_LENGTH, &result);
2881     if (status != napi_ok) {
2882         HiLog::Error(LABEL, "GetIndex Failed");
2883         return nullptr;
2884     }
2885     return result;
2886 }
2887 
Is24HourClock(napi_env env,napi_callback_info info)2888 napi_value I18nAddon::Is24HourClock(napi_env env, napi_callback_info info)
2889 {
2890     bool is24HourClock = LocaleConfig::Is24HourClock();
2891     napi_value result = nullptr;
2892     napi_status status = napi_get_boolean(env, is24HourClock, &result);
2893     if (status != napi_ok) {
2894         HiLog::Error(LABEL, "Failed to create boolean item");
2895         return nullptr;
2896     }
2897     return result;
2898 }
2899 
Set24HourClock(napi_env env,napi_callback_info info)2900 napi_value I18nAddon::Set24HourClock(napi_env env, napi_callback_info info)
2901 {
2902     return I18nAddon::Set24HourClockImpl(env, info, false);
2903 }
2904 
Set24HourClockWithError(napi_env env,napi_callback_info info)2905 napi_value I18nAddon::Set24HourClockWithError(napi_env env, napi_callback_info info)
2906 {
2907     return I18nAddon::Set24HourClockImpl(env, info, true);
2908 }
2909 
Set24HourClockImpl(napi_env env,napi_callback_info info,bool throwError)2910 napi_value I18nAddon::Set24HourClockImpl(napi_env env, napi_callback_info info, bool throwError)
2911 {
2912     size_t argc = 1;
2913     napi_value argv[1] = { 0 };
2914     napi_value thisVar = nullptr;
2915     void *data = nullptr;
2916     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2917     if (status != napi_ok) {
2918         return nullptr;
2919     }
2920     if (argv[0] == nullptr) {
2921         HiLog::Error(LABEL, "Missing parameter");
2922         ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, throwError);
2923         return nullptr;
2924     }
2925 
2926     bool option = false;
2927     status = napi_get_value_bool(env, argv[0], &option);
2928     if (status != napi_ok) {
2929         HiLog::Error(LABEL, "Failed to get boolean item");
2930         ErrorUtil::NapiThrow(env, I18N_NOT_VALID, throwError);
2931         return nullptr;
2932     }
2933     bool success = LocaleConfig::Set24HourClock(option);
2934     if (throwError) {
2935         if (!success) {
2936             ErrorUtil::NapiThrow(env, I18N_NO_PERMISSION, throwError);
2937         }
2938         return nullptr;
2939     }
2940     napi_value result = nullptr;
2941     status = napi_get_boolean(env, success, &result);
2942     if (status != napi_ok) {
2943         HiLog::Error(LABEL, "Create set 24HourClock boolean value failed");
2944         return nullptr;
2945     }
2946     return result;
2947 }
2948 
AddPreferredLanguage(napi_env env,napi_callback_info info)2949 napi_value I18nAddon::AddPreferredLanguage(napi_env env, napi_callback_info info)
2950 {
2951     return I18nAddon::AddPreferredLanguageImpl(env, info, false);
2952 }
2953 
AddPreferredLanguageWithError(napi_env env,napi_callback_info info)2954 napi_value I18nAddon::AddPreferredLanguageWithError(napi_env env, napi_callback_info info)
2955 {
2956     return I18nAddon::AddPreferredLanguageImpl(env, info, true);
2957 }
2958 
ParseStringParam(napi_env env,napi_value argv,bool throwError,std::string & strParam)2959 bool I18nAddon::ParseStringParam(napi_env env, napi_value argv, bool throwError, std::string &strParam)
2960 {
2961     if (argv == nullptr) {
2962         HiLog::Error(LABEL, "Missing parameter");
2963         ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, throwError);
2964         return false;
2965     }
2966     napi_valuetype valueType = napi_valuetype::napi_undefined;
2967     napi_typeof(env, argv, &valueType);
2968     if (valueType != napi_valuetype::napi_string) {
2969         ErrorUtil::NapiThrow(env, I18N_NOT_VALID, throwError);
2970         return false;
2971     }
2972     size_t len = 0;
2973     napi_status status = napi_get_value_string_utf8(env, argv, nullptr, 0, &len);
2974     if (status != napi_ok) {
2975         HiLog::Error(LABEL, "get string parameter length failed");
2976         ErrorUtil::NapiThrow(env, I18N_NOT_VALID, throwError);
2977         return false;
2978     }
2979     std::vector<char> res(len + 1);
2980     status = napi_get_value_string_utf8(env, argv, res.data(), len + 1, &len);
2981     if (status != napi_ok) {
2982         HiLog::Error(LABEL, "get string parameter failed");
2983         return false;
2984     }
2985     strParam = res.data();
2986     return true;
2987 }
2988 
AddPreferredLanguageImpl(napi_env env,napi_callback_info info,bool throwError)2989 napi_value I18nAddon::AddPreferredLanguageImpl(napi_env env, napi_callback_info info, bool throwError)
2990 {
2991     size_t argc = 2;
2992     napi_value argv[2] = { 0 };
2993     napi_value thisVar = nullptr;
2994     void *data = nullptr;
2995     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2996     if (status != napi_ok) {
2997         return nullptr;
2998     }
2999 
3000     std::string language;
3001     if (!ParseStringParam(env, argv[0], throwError, language)) {
3002         return nullptr;
3003     }
3004 
3005     int index = 1000000;
3006     if (CheckNapiValueType(env, argv[1])) {
3007         status = napi_get_value_int32(env, argv[1], &index);
3008     }
3009     if (status != napi_ok) {
3010         HiLog::Error(LABEL, "addPreferrdLanguage: get index failed");
3011         ErrorUtil::NapiThrow(env, I18N_NOT_VALID, throwError);
3012         return nullptr;
3013     }
3014     I18nErrorCode errorCode = I18nErrorCode::SUCCESS;
3015     PreferredLanguage::AddPreferredLanguage(language.data(), index, errorCode);
3016     if (throwError) {
3017         if (errorCode == I18nErrorCode::NO_PERMISSION) {
3018             ErrorUtil::NapiThrow(env, I18N_NO_PERMISSION, throwError);
3019         }
3020         if (errorCode == I18nErrorCode::INVALID_PARAMETER || errorCode == I18nErrorCode::FAILED) {
3021             ErrorUtil::NapiThrow(env, I18N_NOT_VALID, throwError);
3022         }
3023         return nullptr;
3024     }
3025     bool addResult = true;
3026     if (errorCode != I18nErrorCode::SUCCESS) {
3027         addResult = false;
3028     }
3029     napi_value result = nullptr;
3030     status = napi_get_boolean(env, addResult, &result);
3031     if (status != napi_ok) {
3032         HiLog::Error(LABEL, "addPreferrdLanguage: create boolean result failed");
3033         return nullptr;
3034     }
3035     return result;
3036 }
3037 
RemovePreferredLanguage(napi_env env,napi_callback_info info)3038 napi_value I18nAddon::RemovePreferredLanguage(napi_env env, napi_callback_info info)
3039 {
3040     return I18nAddon::RemovePreferredLanguageImpl(env, info, false);
3041 }
3042 
RemovePreferredLanguageWithError(napi_env env,napi_callback_info info)3043 napi_value I18nAddon::RemovePreferredLanguageWithError(napi_env env, napi_callback_info info)
3044 {
3045     return I18nAddon::RemovePreferredLanguageImpl(env, info, true);
3046 }
3047 
RemovePreferredLanguageImpl(napi_env env,napi_callback_info info,bool throwError)3048 napi_value I18nAddon::RemovePreferredLanguageImpl(napi_env env, napi_callback_info info, bool throwError)
3049 {
3050     size_t argc = 1;
3051     napi_value argv[1] = { 0 };
3052     napi_value thisVar = nullptr;
3053     void *data = nullptr;
3054     int len = 0;
3055     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
3056     if (status != napi_ok) {
3057         return nullptr;
3058     }
3059     if (argv[0] == nullptr) {
3060         HiLog::Error(LABEL, "Missing parameter");
3061         ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, throwError);
3062         return nullptr;
3063     }
3064 
3065     napi_valuetype valueType = napi_valuetype::napi_undefined;
3066     napi_typeof(env, argv[0], &valueType);
3067     if (valueType != napi_valuetype::napi_number) {
3068         ErrorUtil::NapiThrow(env, I18N_NOT_VALID, throwError);
3069         return nullptr;
3070     }
3071     int index = 1000000;
3072     status = napi_get_value_int32(env, argv[0], &index);
3073     if (status != napi_ok) {
3074         HiLog::Error(LABEL, "removePreferrdLanguage: get index failed");
3075         ErrorUtil::NapiThrow(env, I18N_NOT_VALID, throwError);
3076         return nullptr;
3077     }
3078     len = static_cast<int>(PreferredLanguage::GetPreferredLanguageList().size());
3079     if ((index < 0 || index > len - 1) && throwError) {
3080         ErrorUtil::NapiThrow(env, I18N_NOT_VALID, throwError);
3081         return nullptr;
3082     }
3083     bool success = PreferredLanguage::RemovePreferredLanguage(index);
3084 
3085     if (throwError) {
3086         if (!success) {
3087             ErrorUtil::NapiThrow(env, I18N_NO_PERMISSION, throwError);
3088         }
3089         return nullptr;
3090     }
3091     napi_value result = nullptr;
3092     status = napi_get_boolean(env, success, &result);
3093     if (status != napi_ok) {
3094         HiLog::Error(LABEL, "removePreferrdLanguage: create boolean result failed");
3095         return nullptr;
3096     }
3097     return result;
3098 }
3099 
GetPreferredLanguageList(napi_env env,napi_callback_info info)3100 napi_value I18nAddon::GetPreferredLanguageList(napi_env env, napi_callback_info info)
3101 {
3102     std::vector<std::string> languageList = PreferredLanguage::GetPreferredLanguageList();
3103     napi_value result = nullptr;
3104     napi_status status = napi_ok;
3105     status = napi_create_array_with_length(env, languageList.size(), &result);
3106     if (status != napi_ok) {
3107         HiLog::Error(LABEL, "getPreferrdLanguageList: create array failed");
3108         return nullptr;
3109     }
3110     for (size_t i = 0; i < languageList.size(); i++) {
3111         napi_value value = nullptr;
3112         status = napi_create_string_utf8(env, languageList[i].c_str(), NAPI_AUTO_LENGTH, &value);
3113         if (status != napi_ok) {
3114             HiLog::Error(LABEL, "getPreferrdLanguageList: create string failed");
3115             return nullptr;
3116         }
3117         status = napi_set_element(env, result, i, value);
3118         if (status != napi_ok) {
3119             HiLog::Error(LABEL, "GetPreferredLanguageList: set array item failed");
3120             return nullptr;
3121         }
3122     }
3123     return result;
3124 }
3125 
GetFirstPreferredLanguage(napi_env env,napi_callback_info info)3126 napi_value I18nAddon::GetFirstPreferredLanguage(napi_env env, napi_callback_info info)
3127 {
3128     std::string language = PreferredLanguage::GetFirstPreferredLanguage();
3129     napi_value result = nullptr;
3130     napi_status status = napi_ok;
3131     status = napi_create_string_utf8(env, language.c_str(), NAPI_AUTO_LENGTH, &result);
3132     if (status != napi_ok) {
3133         HiLog::Error(LABEL, "getFirstPreferrdLanguage: create string result failed");
3134         return nullptr;
3135     }
3136     return result;
3137 }
3138 
GetAppPreferredLanguage(napi_env env,napi_callback_info info)3139 napi_value I18nAddon::GetAppPreferredLanguage(napi_env env, napi_callback_info info)
3140 {
3141 #ifdef SUPPORT_APP_PREFERRED_LANGUAGE
3142     std::string language = PreferredLanguage::GetAppPreferredLanguage();
3143 #else
3144     std::string language = PreferredLanguage::GetFirstPreferredLanguage();
3145 #endif
3146     napi_value result = nullptr;
3147     napi_status status = napi_ok;
3148     status = napi_create_string_utf8(env, language.c_str(), NAPI_AUTO_LENGTH, &result);
3149     if (status != napi_ok) {
3150         HiLog::Error(LABEL, "getAppPreferrdLanguage: create string result failed");
3151         return nullptr;
3152     }
3153     return result;
3154 }
3155 
InitI18nTimeZone(napi_env env,napi_value exports)3156 napi_value I18nAddon::InitI18nTimeZone(napi_env env, napi_value exports)
3157 {
3158     napi_status status = napi_ok;
3159     napi_property_descriptor properties[] = {
3160         DECLARE_NAPI_FUNCTION("getID", GetID),
3161         DECLARE_NAPI_FUNCTION("getDisplayName", GetTimeZoneDisplayName),
3162         DECLARE_NAPI_FUNCTION("getRawOffset", GetRawOffset),
3163         DECLARE_NAPI_FUNCTION("getOffset", GetOffset),
3164     };
3165     napi_value constructor = nullptr;
3166     status = napi_define_class(env, "TimeZone", NAPI_AUTO_LENGTH, I18nTimeZoneConstructor, nullptr,
3167         sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor);
3168     if (status != napi_ok) {
3169         HiLog::Error(LABEL, "Failed to define class TimeZone at Init");
3170         return nullptr;
3171     }
3172     g_timezoneConstructor = new (std::nothrow) napi_ref;
3173     if (!g_timezoneConstructor) {
3174         HiLog::Error(LABEL, "Failed to create TimeZone ref at init");
3175         return nullptr;
3176     }
3177     status = napi_create_reference(env, constructor, 1, g_timezoneConstructor);
3178     if (status != napi_ok) {
3179         HiLog::Error(LABEL, "Failed to create reference g_timezoneConstructor at init");
3180         return nullptr;
3181     }
3182     return exports;
3183 }
3184 
I18nTimeZoneConstructor(napi_env env,napi_callback_info info)3185 napi_value I18nAddon::I18nTimeZoneConstructor(napi_env env, napi_callback_info info)
3186 {
3187     size_t argc = 2;
3188     napi_value argv[2] = { nullptr };
3189     napi_value thisVar = nullptr;
3190     void *data = nullptr;
3191     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
3192     if (status != napi_ok) {
3193         return nullptr;
3194     }
3195     std::string zoneID = "";
3196     napi_valuetype valueType = napi_valuetype::napi_undefined;
3197     if (argv[0] != nullptr) {
3198         napi_typeof(env, argv[0], &valueType);
3199         if (valueType != napi_valuetype::napi_string) {
3200             return nullptr;
3201         }
3202         int32_t code = 0;
3203         zoneID = GetString(env, argv[0], code);
3204         if (code != 0) {
3205             return nullptr;
3206         }
3207     }
3208     if (argv[1] == nullptr) {
3209         return nullptr;
3210     }
3211     napi_typeof(env, argv[1], &valueType);
3212     if (valueType != napi_valuetype::napi_boolean) {
3213         return nullptr;
3214     }
3215     bool isZoneID = false;
3216     status = napi_get_value_bool(env, argv[1], &isZoneID);
3217     if (status != napi_ok) {
3218         return nullptr;
3219     }
3220     std::unique_ptr<I18nAddon> obj = std::make_unique<I18nAddon>();
3221     status =
3222         napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()), I18nAddon::Destructor, nullptr, nullptr);
3223     if (status != napi_ok) {
3224         return nullptr;
3225     }
3226     obj->timezone_ = I18nTimeZone::CreateInstance(zoneID, isZoneID);
3227     if (!obj->timezone_) {
3228         return nullptr;
3229     }
3230     obj.release();
3231     return thisVar;
3232 }
3233 
GetI18nTimeZone(napi_env env,napi_callback_info info)3234 napi_value I18nAddon::GetI18nTimeZone(napi_env env, napi_callback_info info)
3235 {
3236     size_t argc = 1;
3237     napi_value argv[1] = { nullptr };
3238     napi_value thisVar = nullptr;
3239     void *data = nullptr;
3240     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
3241     if (!CheckNapiValueType(env, argv[0])) {
3242         napi_create_string_utf8(env, "", NAPI_AUTO_LENGTH, &argv[0]);
3243     }
3244     return StaticGetTimeZone(env, argv, true);
3245 }
3246 
GetID(napi_env env,napi_callback_info info)3247 napi_value I18nAddon::GetID(napi_env env, napi_callback_info info)
3248 {
3249     size_t argc = 0;
3250     napi_value *argv = nullptr;
3251     napi_value thisVar = nullptr;
3252     void *data = nullptr;
3253     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
3254     I18nAddon *obj = nullptr;
3255     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
3256     if (status != napi_ok || !obj || !obj->timezone_) {
3257         HiLog::Error(LABEL, "Get TimeZone object failed");
3258         return nullptr;
3259     }
3260     std::string result = obj->timezone_->GetID();
3261     napi_value value = nullptr;
3262     status = napi_create_string_utf8(env, result.c_str(), NAPI_AUTO_LENGTH, &value);
3263     if (status != napi_ok) {
3264         HiLog::Error(LABEL, "Create result failed");
3265         return nullptr;
3266     }
3267     return value;
3268 }
3269 
GetStringFromJS(napi_env env,napi_value argv,std::string & jsString)3270 bool I18nAddon::GetStringFromJS(napi_env env, napi_value argv, std::string &jsString)
3271 {
3272     size_t len = 0;
3273     napi_status status = napi_get_value_string_utf8(env, argv, nullptr, 0, &len);
3274     if (status != napi_ok) {
3275         HiLog::Error(LABEL, "Failed to get string length");
3276         return false;
3277     }
3278     std::vector<char> argvBuf(len + 1);
3279     status = napi_get_value_string_utf8(env, argv, argvBuf.data(), len + 1, &len);
3280     if (status != napi_ok) {
3281         HiLog::Error(LABEL, "Failed to get string item");
3282         return false;
3283     }
3284     jsString = argvBuf.data();
3285     return true;
3286 }
3287 
GetParameter(napi_env env,napi_value * argv,std::string & localeStr,bool & isDST)3288 int32_t I18nAddon::GetParameter(napi_env env, napi_value *argv, std::string &localeStr, bool &isDST)
3289 {
3290     napi_status status = napi_ok;
3291     if (CheckNapiValueType(env, argv[1])) {
3292         napi_valuetype valueType0 = napi_valuetype::napi_undefined;
3293         napi_valuetype valueType1 = napi_valuetype::napi_undefined;
3294         napi_typeof(env, argv[0], &valueType0);  // 0 represents first parameter
3295         napi_typeof(env, argv[1], &valueType1);  // 1 represents second parameter
3296         bool firstParamFlag = CheckNapiValueType(env, argv[0]);
3297         if (valueType1 == napi_valuetype::napi_boolean) {
3298             status = napi_get_value_bool(env, argv[1], &isDST);
3299             if (status != napi_ok) {
3300                 return -1;  // -1 represents Invalid parameter.
3301             } else if (!firstParamFlag) {
3302                 return 2;  // 2 represents one boolean parameter.
3303             }
3304             if (valueType0 == napi_valuetype::napi_string &&
3305                  GetStringFromJS(env, argv[0], localeStr)) {
3306                 return 3;  // 3 represents one string parameter and one bool parameter.
3307             }
3308         }
3309         return -1;  // -1 represents Invalid parameter.
3310     }
3311     return GetFirstParameter(env, argv[0], localeStr, isDST);
3312 }
3313 
GetFirstParameter(napi_env env,napi_value value,std::string & localeStr,bool & isDST)3314 int32_t I18nAddon::GetFirstParameter(napi_env env, napi_value value, std::string &localeStr, bool &isDST)
3315 {
3316     if (!CheckNapiValueType(env, value)) {
3317         return 0;  // 0 represents no parameter.
3318     } else {
3319         napi_status status = napi_ok;
3320         napi_valuetype valueType = napi_valuetype::napi_undefined;
3321         napi_typeof(env, value, &valueType);
3322         if (valueType == napi_valuetype::napi_string) {
3323             bool valid = GetStringFromJS(env, value, localeStr);
3324             // -1 represents Invalid parameter.
3325             // 1 represents one string parameter.
3326             return !valid ? -1 : 1;
3327         } else if (valueType == napi_valuetype::napi_boolean) {
3328             status = napi_get_value_bool(env, value, &isDST);
3329             // -1 represents Invalid parameter.
3330             // 2 represents one boolean parameter.
3331             return (status != napi_ok) ? -1 : 2;
3332         }
3333         return -1;  // -1 represents Invalid parameter.
3334     }
3335 }
3336 
GetTimeZoneDisplayName(napi_env env,napi_callback_info info)3337 napi_value I18nAddon::GetTimeZoneDisplayName(napi_env env, napi_callback_info info)
3338 {
3339     size_t argc = 2;
3340     napi_value argv[2] = { 0 };
3341     napi_value thisVar = nullptr;
3342     void *data = nullptr;
3343     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
3344     if (status != napi_ok) {
3345         return nullptr;
3346     }
3347 
3348     I18nAddon *obj = nullptr;
3349     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
3350     if (status != napi_ok || !obj || !obj->timezone_) {
3351         HiLog::Error(LABEL, "Get TimeZone object failed");
3352         return nullptr;
3353     }
3354 
3355     std::string locale;
3356     bool isDST = false;
3357     int32_t parameterStatus = GetParameter(env, argv, locale, isDST);
3358 
3359     std::string result;
3360     if (parameterStatus == -1) {  // -1 represents Invalid parameter.
3361         napi_throw_type_error(env, nullptr, "Parameter type does not match");
3362         return nullptr;
3363     } else if (parameterStatus == 0) {
3364         result = obj->timezone_->GetDisplayName();
3365     } else if (parameterStatus == 1) {  // 1 represents one string parameter.
3366         result = obj->timezone_->GetDisplayName(locale);
3367     } else if (parameterStatus == 2) {  // 2 represents one boolean parameter.
3368         result = obj->timezone_->GetDisplayName(isDST);
3369     } else {
3370         result = obj->timezone_->GetDisplayName(locale, isDST);
3371     }
3372 
3373     napi_value value = nullptr;
3374     status = napi_create_string_utf8(env, result.c_str(), NAPI_AUTO_LENGTH, &value);
3375     if (status != napi_ok) {
3376         HiLog::Error(LABEL, "Create result failed");
3377         return nullptr;
3378     }
3379     return value;
3380 }
3381 
GetOffset(napi_env env,napi_callback_info info)3382 napi_value I18nAddon::GetOffset(napi_env env, napi_callback_info info)
3383 {
3384     size_t argc = 1;
3385     napi_value argv[1] = { 0 };
3386     napi_value thisVar = nullptr;
3387     void *data = nullptr;
3388     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
3389     if (status != napi_ok) {
3390         return nullptr;
3391     }
3392 
3393     double date = 0;
3394     if (CheckNapiValueType(env, argv[0])) {
3395         napi_valuetype valueType = napi_valuetype::napi_undefined;
3396         napi_typeof(env, argv[0], &valueType);
3397         if (valueType != napi_valuetype::napi_number) {
3398             HiLog::Error(LABEL, "Invalid parameter type");
3399             return nullptr;
3400         }
3401         status = napi_get_value_double(env, argv[0], &date);
3402         if (status != napi_ok) {
3403             HiLog::Error(LABEL, "Get parameter date failed");
3404             return nullptr;
3405         }
3406     } else {
3407         auto time = std::chrono::system_clock::now();
3408         auto since_epoch = time.time_since_epoch();
3409         auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(since_epoch);
3410         date = (double)millis.count();
3411     }
3412 
3413     I18nAddon *obj = nullptr;
3414     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
3415     if (status != napi_ok || !obj || !obj->timezone_) {
3416         HiLog::Error(LABEL, "Get TimeZone object failed");
3417         return nullptr;
3418     }
3419     int32_t result = obj->timezone_->GetOffset(date);
3420     napi_value value = nullptr;
3421     status = napi_create_int32(env, result, &value);
3422     if (status != napi_ok) {
3423         HiLog::Error(LABEL, "Create result failed");
3424         return nullptr;
3425     }
3426     return value;
3427 }
3428 
GetRawOffset(napi_env env,napi_callback_info info)3429 napi_value I18nAddon::GetRawOffset(napi_env env, napi_callback_info info)
3430 {
3431     size_t argc = 0;
3432     napi_value *argv = nullptr;
3433     napi_value thisVar = nullptr;
3434     void *data = nullptr;
3435     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
3436     I18nAddon *obj = nullptr;
3437     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
3438     if (status != napi_ok || !obj || !obj->timezone_) {
3439         HiLog::Error(LABEL, "Get TimeZone object failed");
3440         return nullptr;
3441     }
3442     int32_t result = obj->timezone_->GetRawOffset();
3443     napi_value value = nullptr;
3444     status = napi_create_int32(env, result, &value);
3445     if (status != napi_ok) {
3446         HiLog::Error(LABEL, "Create result failed");
3447         return nullptr;
3448     }
3449     return value;
3450 }
3451 
SetUsingLocalDigitAddon(napi_env env,napi_callback_info info)3452 napi_value I18nAddon::SetUsingLocalDigitAddon(napi_env env, napi_callback_info info)
3453 {
3454     return I18nAddon::SetUsingLocalDigitAddonImpl(env, info, false);
3455 }
3456 
SetUsingLocalDigitAddonWithError(napi_env env,napi_callback_info info)3457 napi_value I18nAddon::SetUsingLocalDigitAddonWithError(napi_env env, napi_callback_info info)
3458 {
3459     return I18nAddon::SetUsingLocalDigitAddonImpl(env, info, true);
3460 }
3461 
SetUsingLocalDigitAddonImpl(napi_env env,napi_callback_info info,bool throwError)3462 napi_value I18nAddon::SetUsingLocalDigitAddonImpl(napi_env env, napi_callback_info info, bool throwError)
3463 {
3464     size_t argc = 1;
3465     napi_value argv[1] = { 0 };
3466     napi_value thisVar = nullptr;
3467     void *data = nullptr;
3468     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
3469 
3470     if (argv[0] == nullptr) {
3471         HiLog::Error(LABEL, "Invalid parameter nullptr");
3472         ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, throwError);
3473         return nullptr;
3474     }
3475     napi_valuetype valueType = napi_valuetype::napi_undefined;
3476     napi_typeof(env, argv[0], &valueType);
3477     if (valueType != napi_valuetype::napi_boolean) {
3478         HiLog::Error(LABEL, "Invalid parameter type");
3479         ErrorUtil::NapiThrow(env, I18N_NOT_VALID, throwError);
3480         return nullptr;
3481     }
3482     bool flag = false;
3483     napi_status status = napi_get_value_bool(env, argv[0], &flag);
3484     if (status != napi_ok) {
3485         HiLog::Error(LABEL, "Get parameter flag failed");
3486         return nullptr;
3487     }
3488 
3489     bool res = LocaleConfig::SetUsingLocalDigit(flag);
3490     if (throwError) {
3491         if (!res) {
3492             ErrorUtil::NapiThrow(env, I18N_NO_PERMISSION, throwError);
3493         }
3494         return nullptr;
3495     }
3496     napi_value value = nullptr;
3497     status = napi_get_boolean(env, res, &value);
3498     if (status != napi_ok) {
3499         HiLog::Error(LABEL, "Invalid result");
3500         return nullptr;
3501     }
3502     return value;
3503 }
3504 
GetUsingLocalDigitAddon(napi_env env,napi_callback_info info)3505 napi_value I18nAddon::GetUsingLocalDigitAddon(napi_env env, napi_callback_info info)
3506 {
3507     bool res = LocaleConfig::GetUsingLocalDigit();
3508     napi_value value = nullptr;
3509     napi_status status = napi_get_boolean(env, res, &value);
3510     if (status != napi_ok) {
3511         return nullptr;
3512     }
3513     return value;
3514 }
3515 
CreateTimeZoneObject(napi_env env,napi_status & initStatus)3516 napi_value I18nAddon::CreateTimeZoneObject(napi_env env, napi_status &initStatus)
3517 {
3518     napi_status status = napi_ok;
3519     napi_value timezone = nullptr;
3520     status = napi_create_object(env, &timezone);
3521     if (status != napi_ok) {
3522         HiLog::Error(LABEL, "Failed to create timezone object at init");
3523         initStatus = napi_generic_failure;
3524         return nullptr;
3525     }
3526     napi_property_descriptor timezoneProperties[] = {
3527         DECLARE_NAPI_FUNCTION("getAvailableIDs", GetAvailableTimezoneIDs),
3528         DECLARE_NAPI_FUNCTION("getAvailableZoneCityIDs", GetAvailableZoneCityIDs),
3529         DECLARE_NAPI_FUNCTION("getCityDisplayName", GetCityDisplayName),
3530         DECLARE_NAPI_FUNCTION("getTimezoneFromCity", GetTimezoneFromCity),
3531         DECLARE_NAPI_FUNCTION("getTimezonesByLocation", GetTimezonesByLocation)
3532     };
3533     status = napi_define_properties(env, timezone,
3534                                     sizeof(timezoneProperties) / sizeof(napi_property_descriptor),
3535                                     timezoneProperties);
3536     if (status != napi_ok) {
3537         HiLog::Error(LABEL, "Failed to set properties of timezone at init");
3538         initStatus = napi_generic_failure;
3539         return nullptr;
3540     }
3541     return timezone;
3542 }
3543 
CreateSystemObject(napi_env env,napi_status & initStatus)3544 napi_value I18nAddon::CreateSystemObject(napi_env env, napi_status &initStatus)
3545 {
3546     napi_status status = napi_ok;
3547     napi_value system = nullptr;
3548     status = napi_create_object(env, &system);
3549     if (status != napi_ok) {
3550         HiLog::Error(LABEL, "Failed to create system object at init");
3551         initStatus = napi_generic_failure;
3552         return nullptr;
3553     }
3554     napi_property_descriptor systemProperties[] = {
3555         DECLARE_NAPI_FUNCTION("getDisplayCountry", GetDisplayCountryWithError),
3556         DECLARE_NAPI_FUNCTION("getDisplayLanguage", GetDisplayLanguageWithError),
3557         DECLARE_NAPI_FUNCTION("getSystemLanguages", GetSystemLanguages),
3558         DECLARE_NAPI_FUNCTION("getSystemCountries", GetSystemCountriesWithError),
3559         DECLARE_NAPI_FUNCTION("isSuggested", IsSuggestedWithError),
3560         DECLARE_NAPI_FUNCTION("getSystemLanguage", GetSystemLanguage),
3561         DECLARE_NAPI_FUNCTION("setSystemLanguage", SetSystemLanguageWithError),
3562         DECLARE_NAPI_FUNCTION("getSystemRegion", GetSystemRegion),
3563         DECLARE_NAPI_FUNCTION("setSystemRegion", SetSystemRegionWithError),
3564         DECLARE_NAPI_FUNCTION("getSystemLocale", GetSystemLocale),
3565         DECLARE_NAPI_FUNCTION("setSystemLocale", SetSystemLocaleWithError),
3566         DECLARE_NAPI_FUNCTION("is24HourClock", Is24HourClock),
3567         DECLARE_NAPI_FUNCTION("set24HourClock", Set24HourClockWithError),
3568         DECLARE_NAPI_FUNCTION("addPreferredLanguage", AddPreferredLanguageWithError),
3569         DECLARE_NAPI_FUNCTION("removePreferredLanguage", RemovePreferredLanguageWithError),
3570         DECLARE_NAPI_FUNCTION("getPreferredLanguageList", GetPreferredLanguageList),
3571         DECLARE_NAPI_FUNCTION("getFirstPreferredLanguage", GetFirstPreferredLanguage),
3572         DECLARE_NAPI_FUNCTION("getAppPreferredLanguage", GetAppPreferredLanguage),
3573         DECLARE_NAPI_FUNCTION("setUsingLocalDigit", SetUsingLocalDigitAddonWithError),
3574         DECLARE_NAPI_FUNCTION("getUsingLocalDigit", GetUsingLocalDigitAddon),
3575     };
3576     status = napi_define_properties(env, system,
3577                                     sizeof(systemProperties) / sizeof(napi_property_descriptor),
3578                                     systemProperties);
3579     if (status != napi_ok) {
3580         HiLog::Error(LABEL, "Failed to set properties of system at init");
3581         initStatus = napi_generic_failure;
3582         return nullptr;
3583     }
3584     return system;
3585 }
3586 
GetAvailableTimezoneIDs(napi_env env,napi_callback_info info)3587 napi_value I18nAddon::GetAvailableTimezoneIDs(napi_env env, napi_callback_info info)
3588 {
3589     I18nErrorCode errorCode = I18nErrorCode::SUCCESS;
3590     std::set<std::string> timezoneIDs = I18nTimeZone::GetAvailableIDs(errorCode);
3591     if (errorCode != I18nErrorCode::SUCCESS) {
3592         return nullptr;
3593     }
3594     napi_value result = nullptr;
3595     napi_status status = napi_create_array_with_length(env, timezoneIDs.size(), &result);
3596     if (status != napi_ok) {
3597         HiLog::Error(LABEL, "Failed to create array");
3598         return nullptr;
3599     }
3600     size_t index = 0;
3601     for (std::set<std::string>::iterator it = timezoneIDs.begin(); it != timezoneIDs.end(); ++it) {
3602         napi_value value = nullptr;
3603         status = napi_create_string_utf8(env, (*it).c_str(), NAPI_AUTO_LENGTH, &value);
3604         if (status != napi_ok) {
3605             HiLog::Error(LABEL, "Failed to create string item");
3606             return nullptr;
3607         }
3608         status = napi_set_element(env, result, index, value);
3609         if (status != napi_ok) {
3610             HiLog::Error(LABEL, "Failed to set array item");
3611             return nullptr;
3612         }
3613         ++index;
3614     }
3615     return result;
3616 }
3617 
GetAvailableZoneCityIDs(napi_env env,napi_callback_info info)3618 napi_value I18nAddon::GetAvailableZoneCityIDs(napi_env env, napi_callback_info info)
3619 {
3620     std::set<std::string> cityIDs = I18nTimeZone::GetAvailableZoneCityIDs();
3621     napi_value result = nullptr;
3622     napi_status status = napi_create_array_with_length(env, cityIDs.size(), &result);
3623     if (status != napi_ok) {
3624         HiLog::Error(LABEL, "Failed to create array");
3625         return nullptr;
3626     }
3627     size_t index = 0;
3628     for (auto it = cityIDs.begin(); it != cityIDs.end(); ++it) {
3629         napi_value value = nullptr;
3630         status = napi_create_string_utf8(env, (*it).c_str(), NAPI_AUTO_LENGTH, &value);
3631         if (status != napi_ok) {
3632             HiLog::Error(LABEL, "GetAvailableZoneCityIDs: Failed to create string item");
3633             return nullptr;
3634         }
3635         status = napi_set_element(env, result, index, value);
3636         if (status != napi_ok) {
3637             HiLog::Error(LABEL, "GetAvailableZoneCityIDs: Failed to set array item");
3638             return nullptr;
3639         }
3640         ++index;
3641     }
3642     return result;
3643 }
3644 
GetCityDisplayName(napi_env env,napi_callback_info info)3645 napi_value I18nAddon::GetCityDisplayName(napi_env env, napi_callback_info info)
3646 {
3647     size_t argc = 2;
3648     napi_value argv[2] = { 0 };
3649     napi_value thisVar = nullptr;
3650     void *data = nullptr;
3651     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
3652     if (status != napi_ok) {
3653         return nullptr;
3654     }
3655     if (argv[0] == nullptr || argv[1] == nullptr) {
3656         return nullptr;
3657     }
3658     napi_valuetype valueType = napi_valuetype::napi_undefined;
3659     napi_typeof(env, argv[0], &valueType);
3660     if (valueType != napi_valuetype::napi_string) {
3661         HiLog::Error(LABEL, "Invalid parameter type");
3662         return nullptr;
3663     }
3664     int32_t code = 0;
3665     std::string cityID = GetString(env, argv[0], code);
3666     if (code != 0) {
3667         return nullptr;
3668     }
3669     std::string locale = GetString(env, argv[1], code);
3670     if (code != 0) {
3671         return nullptr;
3672     }
3673     std::string name = I18nTimeZone::GetCityDisplayName(cityID, locale);
3674     napi_value result = nullptr;
3675     status = napi_create_string_utf8(env, name.c_str(), NAPI_AUTO_LENGTH, &result);
3676     if (status != napi_ok) {
3677         return nullptr;
3678     }
3679     return result;
3680 }
3681 
StaticGetTimeZone(napi_env env,napi_value * argv,bool isZoneID)3682 napi_value I18nAddon::StaticGetTimeZone(napi_env env, napi_value *argv, bool isZoneID)
3683 {
3684     napi_value constructor = nullptr;
3685     napi_status status = napi_get_reference_value(env, *g_timezoneConstructor, &constructor);
3686     if (status != napi_ok) {
3687         HiLog::Error(LABEL, "Failed to create reference at StaticGetTimeZone");
3688         return nullptr;
3689     }
3690     napi_value newArgv[2] = { 0 };
3691     newArgv[0] = argv[0];
3692     status = napi_get_boolean(env, isZoneID, &newArgv[1]);
3693     if (status != napi_ok) {
3694         return nullptr;
3695     }
3696     napi_value result = nullptr;
3697     status = napi_new_instance(env, constructor, 2, newArgv, &result); // 2 is parameter num
3698     if (status != napi_ok) {
3699         HiLog::Error(LABEL, "StaticGetTimeZone create instance failed");
3700         return nullptr;
3701     }
3702     return result;
3703 }
3704 
GetTimezoneFromCity(napi_env env,napi_callback_info info)3705 napi_value I18nAddon::GetTimezoneFromCity(napi_env env, napi_callback_info info)
3706 {
3707     size_t argc = 1;
3708     napi_value argv[1] = { nullptr };
3709     napi_value thisVar = nullptr;
3710     void *data = nullptr;
3711     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
3712     return StaticGetTimeZone(env, argv, false);
3713 }
3714 
InitCharacter(napi_env env,napi_value exports)3715 napi_value I18nAddon::InitCharacter(napi_env env, napi_value exports)
3716 {
3717     napi_status status = napi_ok;
3718     napi_property_descriptor properties[] = {
3719         DECLARE_NAPI_FUNCTION("isDigit", IsDigitAddon),
3720         DECLARE_NAPI_FUNCTION("isSpaceChar", IsSpaceCharAddon),
3721         DECLARE_NAPI_FUNCTION("isWhitespace", IsWhiteSpaceAddon),
3722         DECLARE_NAPI_FUNCTION("isRTL", IsRTLCharacterAddon),
3723         DECLARE_NAPI_FUNCTION("isIdeograph", IsIdeoGraphicAddon),
3724         DECLARE_NAPI_FUNCTION("isLetter", IsLetterAddon),
3725         DECLARE_NAPI_FUNCTION("isLowerCase", IsLowerCaseAddon),
3726         DECLARE_NAPI_FUNCTION("isUpperCase", IsUpperCaseAddon),
3727         DECLARE_NAPI_FUNCTION("getType", GetTypeAddon)
3728     };
3729 
3730     napi_value constructor = nullptr;
3731     status = napi_define_class(env, "Character", NAPI_AUTO_LENGTH, ObjectConstructor, nullptr,
3732         sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor);
3733     if (status != napi_ok) {
3734         HiLog::Error(LABEL, "Define class failed when InitCharacter");
3735         return nullptr;
3736     }
3737 
3738     status = napi_set_named_property(env, exports, "Character", constructor);
3739     if (status != napi_ok) {
3740         HiLog::Error(LABEL, "Set property failed when InitCharacter");
3741         return nullptr;
3742     }
3743     return exports;
3744 }
3745 
ObjectConstructor(napi_env env,napi_callback_info info)3746 napi_value I18nAddon::ObjectConstructor(napi_env env, napi_callback_info info)
3747 {
3748     size_t argc = 0;
3749     napi_value argv[0];
3750     napi_value thisVar = nullptr;
3751     void *data = nullptr;
3752     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
3753     if (status != napi_ok) {
3754         return nullptr;
3755     }
3756     std::unique_ptr<I18nAddon> obj = nullptr;
3757     obj = std::make_unique<I18nAddon>();
3758     status =
3759         napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()), I18nAddon::Destructor, nullptr, nullptr);
3760     if (status != napi_ok) {
3761         HiLog::Error(LABEL, "Wrap I18nAddon failed");
3762         return nullptr;
3763     }
3764     obj.release();
3765     return thisVar;
3766 }
3767 
InitUtil(napi_env env,napi_value exports)3768 napi_value I18nAddon::InitUtil(napi_env env, napi_value exports)
3769 {
3770     napi_status status = napi_ok;
3771     napi_property_descriptor properties[] = {
3772         DECLARE_NAPI_FUNCTION("unitConvert", UnitConvert)
3773     };
3774 
3775     napi_value constructor = nullptr;
3776     status = napi_define_class(env, "Util", NAPI_AUTO_LENGTH, ObjectConstructor, nullptr,
3777         sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor);
3778     if (status != napi_ok) {
3779         HiLog::Error(LABEL, "Define class failed when InitUtil");
3780         return nullptr;
3781     }
3782 
3783     status = napi_set_named_property(env, exports, "Util", constructor);
3784     if (status != napi_ok) {
3785         HiLog::Error(LABEL, "Set property failed when InitUtil");
3786         return nullptr;
3787     }
3788     return exports;
3789 }
3790 
GetTimezonesByLocation(napi_env env,napi_callback_info info)3791 napi_value I18nAddon::GetTimezonesByLocation(napi_env env, napi_callback_info info)
3792 {
3793     size_t argc = 2;
3794     napi_value argv[2] = {0, 0};
3795     napi_value thisVar = nullptr;
3796     void *data = nullptr;
3797     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
3798     if (status != napi_ok) {
3799         return nullptr;
3800     }
3801     if (argv[0] == nullptr || argv[1] == nullptr) {
3802         HiLog::Error(LABEL, "GetTimezonesByLocation: Missing parameter");
3803         ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, true);
3804         return nullptr;
3805     }
3806     double x, y;
3807     status = napi_get_value_double(env, argv[0], &x);
3808     if (status != napi_ok) {
3809         HiLog::Error(LABEL, "GetTimezonesByLocation: Parse first argument x failed");
3810         ErrorUtil::NapiThrow(env, I18N_NOT_VALID, true);
3811         return nullptr;
3812     }
3813     status = napi_get_value_double(env, argv[1], &y);
3814     if (status != napi_ok) {
3815         HiLog::Error(LABEL, "GetTimezonesByLocation: Parse second argument y failed");
3816         ErrorUtil::NapiThrow(env, I18N_NOT_VALID, true);
3817         return nullptr;
3818     }
3819     // -180 and 179.9 is the scope of longitude, -90 and 89.9 is the scope of latitude
3820     if (x < -180 || x > 179.9 || y < -90 || y > 89.9) {
3821         HiLog::Error(LABEL, "GetTimezonesByLocation: Args x or y exceed it's scope.");
3822         ErrorUtil::NapiThrow(env, I18N_NOT_VALID, true);
3823         return nullptr;
3824     }
3825     napi_value timezoneList = nullptr;
3826     napi_create_array(env, &timezoneList);
3827     std::vector<std::string> tempList = I18nTimeZone::GetTimezoneIdByLocation(x, y);
3828     for (size_t i = 0; i < tempList.size(); i++) {
3829         napi_value timezoneId = nullptr;
3830         status = napi_create_string_utf8(env, tempList[i].c_str(), NAPI_AUTO_LENGTH, &timezoneId);
3831         if (status != napi_ok) {
3832             return nullptr;
3833         }
3834         napi_value argTimeZoneId[1] = { timezoneId };
3835         napi_value timezone = StaticGetTimeZone(env, argTimeZoneId, true);
3836         status = napi_set_element(env, timezoneList, i, timezone);
3837         if (status != napi_ok) {
3838             return nullptr;
3839         }
3840     }
3841 
3842     return timezoneList;
3843 }
3844 
Init(napi_env env,napi_value exports)3845 napi_value Init(napi_env env, napi_value exports)
3846 {
3847     napi_value val = I18nAddon::Init(env, exports);
3848     val = I18nAddon::InitPhoneNumberFormat(env, val);
3849     val = I18nAddon::InitBreakIterator(env, val);
3850     val = I18nAddon::InitI18nCalendar(env, val);
3851     val = I18nAddon::InitIndexUtil(env, val);
3852     val = I18nAddon::InitI18nTimeZone(env, val);
3853     val = I18nAddon::InitTransliterator(env, val);
3854     val = I18nAddon::InitCharacter(env, val);
3855     val = I18nAddon::InitUtil(env, val);
3856     val = I18nNormalizerAddon::InitI18nNormalizer(env, val);
3857     val = SystemLocaleManagerAddon::InitSystemLocaleManager(env, val);
3858     return val;
3859 }
3860 
3861 static napi_module g_i18nModule = {
3862     .nm_version = 1,
3863     .nm_flags = 0,
3864     .nm_filename = nullptr,
3865     .nm_register_func = Init,
3866     .nm_modname = "i18n",
3867     .nm_priv = nullptr,
3868     .reserved = { 0 }
3869 };
3870 
I18nRegister()3871 extern "C" __attribute__((constructor)) void I18nRegister()
3872 {
3873     napi_module_register(&g_i18nModule);
3874 }
3875 } // namespace I18n
3876 } // namespace Global
3877 } // namespace OHOS
3878