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