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