• 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 #include "character.h"
19 #include "hilog/log.h"
20 #include "i18n_calendar.h"
21 #include "node_api.h"
22 #include "i18n_addon.h"
23 
24 namespace OHOS {
25 namespace Global {
26 namespace I18n {
27 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, 0xD001E00, "I18nJs" };
28 static thread_local napi_ref* g_constructor = nullptr;
29 static thread_local napi_ref* g_brkConstructor = nullptr;
30 static thread_local napi_ref* g_timezoneConstructor = nullptr;
31 static thread_local napi_ref g_indexUtilConstructor = nullptr;
32 static std::unordered_map<std::string, UCalendarDateFields> g_fieldsMap {
33     { "era", UCAL_ERA },
34     { "year", UCAL_YEAR },
35     { "month", UCAL_MONTH },
36     { "week_of_year", UCAL_WEEK_OF_YEAR },
37     { "week_of_month", UCAL_WEEK_OF_MONTH },
38     { "date", UCAL_DATE },
39     { "day_of_year", UCAL_DAY_OF_YEAR },
40     { "day_of_week", UCAL_DAY_OF_WEEK },
41     { "day_of_week_in_month", UCAL_DAY_OF_WEEK_IN_MONTH },
42     { "ap_pm", UCAL_AM_PM },
43     { "hour", UCAL_HOUR },
44     { "hour_of_day", UCAL_HOUR_OF_DAY },
45     { "minute", UCAL_MINUTE },
46     { "second", UCAL_SECOND },
47     { "millisecond", UCAL_MILLISECOND },
48     { "zone_offset", UCAL_ZONE_OFFSET },
49     { "dst_offset", UCAL_DST_OFFSET },
50     { "year_woy", UCAL_YEAR_WOY },
51     { "dow_local", UCAL_DOW_LOCAL },
52     { "extended_year", UCAL_EXTENDED_YEAR },
53     { "julian_day", UCAL_JULIAN_DAY },
54     { "milliseconds_in_day", UCAL_MILLISECONDS_IN_DAY },
55     { "is_leap_month", UCAL_IS_LEAP_MONTH },
56 };
57 static std::unordered_map<std::string, CalendarType> g_typeMap {
58     { "buddhist", CalendarType::BUDDHIST },
59     { "chinese", CalendarType::CHINESE },
60     { "coptic", CalendarType::COPTIC },
61     { "ethiopic", CalendarType::ETHIOPIC },
62     { "hebrew", CalendarType::HEBREW },
63     { "gregory", CalendarType::GREGORY },
64     { "indian", CalendarType::INDIAN },
65     { "islamic_civil", CalendarType::ISLAMIC_CIVIL },
66     { "islamic_tbla", CalendarType::ISLAMIC_TBLA },
67     { "islamic_umalqura", CalendarType::ISLAMIC_UMALQURA },
68     { "japanese", CalendarType::JAPANESE },
69     { "persion", CalendarType::PERSIAN },
70 };
71 using namespace OHOS::HiviewDFX;
72 
I18nAddon()73 I18nAddon::I18nAddon() : env_(nullptr), wrapper_(nullptr) {}
74 
~I18nAddon()75 I18nAddon::~I18nAddon()
76 {
77     napi_delete_reference(env_, wrapper_);
78 }
79 
Destructor(napi_env env,void * nativeObject,void * hint)80 void I18nAddon::Destructor(napi_env env, void *nativeObject, void *hint)
81 {
82     if (!nativeObject) {
83         return;
84     }
85     reinterpret_cast<I18nAddon *>(nativeObject)->~I18nAddon();
86 }
87 
CreateCharacterObject(napi_env env)88 napi_value I18nAddon::CreateCharacterObject(napi_env env)
89 {
90     napi_status status = napi_ok;
91     napi_value character = nullptr;
92     status = napi_create_object(env, &character);
93     if (status != napi_ok) {
94         HiLog::Error(LABEL, "Failed to create character object at init");
95         return nullptr;
96     }
97     napi_property_descriptor characterProperties[] = {
98         DECLARE_NAPI_FUNCTION("isDigit", IsDigitAddon),
99         DECLARE_NAPI_FUNCTION("isSpaceChar", IsSpaceCharAddon),
100         DECLARE_NAPI_FUNCTION("isWhitespace", IsWhiteSpaceAddon),
101         DECLARE_NAPI_FUNCTION("isRTL", IsRTLCharacterAddon),
102         DECLARE_NAPI_FUNCTION("isIdeograph", IsIdeoGraphicAddon),
103         DECLARE_NAPI_FUNCTION("isLetter", IsLetterAddon),
104         DECLARE_NAPI_FUNCTION("isLowerCase", IsLowerCaseAddon),
105         DECLARE_NAPI_FUNCTION("isUpperCase", IsUpperCaseAddon),
106         DECLARE_NAPI_FUNCTION("getType", GetTypeAddon),
107     };
108     status = napi_define_properties(env, character,
109                                     sizeof(characterProperties) / sizeof(napi_property_descriptor),
110                                     characterProperties);
111     if (status != napi_ok) {
112         HiLog::Error(LABEL, "Failed to set properties of character at init");
113         return nullptr;
114     }
115     return character;
116 }
117 
CreateInitProperties(napi_property_descriptor * properties)118 void I18nAddon::CreateInitProperties(napi_property_descriptor *properties)
119 {
120     properties[0] = DECLARE_NAPI_FUNCTION("getSystemLanguages", GetSystemLanguages);  // 0 is properties index
121     properties[1] = DECLARE_NAPI_FUNCTION("getSystemCountries", GetSystemCountries);  // 1 is properties index
122     properties[2] = DECLARE_NAPI_FUNCTION("isSuggested", IsSuggested);  // 2 is properties index
123     properties[3] = DECLARE_NAPI_FUNCTION("getDisplayLanguage", GetDisplayLanguage);  // 3 is properties index
124     properties[4] = DECLARE_NAPI_FUNCTION("getDisplayCountry", GetDisplayCountry);  // 4 is properties index
125     properties[5] = DECLARE_NAPI_FUNCTION("getSystemLanguage", GetSystemLanguage);  // 5 is properties index
126     properties[6] = DECLARE_NAPI_FUNCTION("getSystemRegion", GetSystemRegion);  // 6 is properties index
127     properties[7] = DECLARE_NAPI_FUNCTION("getSystemLocale", GetSystemLocale);  // 7 is properties index
128     properties[8] = DECLARE_NAPI_FUNCTION("setSystemLanguage", SetSystemLanguage);  // 8 is properties index
129     properties[9] = DECLARE_NAPI_FUNCTION("setSystemRegion", SetSystemRegion);  // 9 is properties index
130     properties[10] = DECLARE_NAPI_FUNCTION("setSystemLocale", SetSystemLocale);  // 10 is properties index
131     properties[11] = DECLARE_NAPI_FUNCTION("getCalendar", GetCalendar);  // 11 is properties index
132     properties[12] = DECLARE_NAPI_FUNCTION("isRTL", IsRTL);  // 12 is properties index
133     properties[14] = DECLARE_NAPI_FUNCTION("getLineInstance", GetLineInstance);  // 14 is properties index
134     properties[15] = DECLARE_NAPI_FUNCTION("getInstance", GetIndexUtil);  // 15 is properties index
135     properties[17] = DECLARE_NAPI_FUNCTION("addPreferredLanguage", AddPreferredLanguage);  // 17 is properties index
136     // 18 is properties index
137     properties[18] = DECLARE_NAPI_FUNCTION("removePreferredLanguage", RemovePreferredLanguage);
138     // 19 is properties index
139     properties[19] = DECLARE_NAPI_FUNCTION("getPreferredLanguageList", GetPreferredLanguageList);
140     // 20 is properties index
141     properties[20] = DECLARE_NAPI_FUNCTION("getFirstPreferredLanguage", GetFirstPreferredLanguage);
142     // 21 is properties index
143     properties[21] = DECLARE_NAPI_FUNCTION("is24HourClock", Is24HourClock);
144     // 22 is properties index
145     properties[22] = DECLARE_NAPI_FUNCTION("set24HourClock", Set24HourClock);
146     // 23 is properties index
147     properties[23] = DECLARE_NAPI_FUNCTION("getTimeZone", GetI18nTimeZone);
148 }
149 
Init(napi_env env,napi_value exports)150 napi_value I18nAddon::Init(napi_env env, napi_value exports)
151 {
152     napi_status status = napi_ok;
153     napi_value util = nullptr;
154     status = napi_create_object(env, &util);
155     if (status != napi_ok) {
156         HiLog::Error(LABEL, "Failed to create util object at init");
157         return nullptr;
158     }
159     napi_property_descriptor utilProperties[] = {
160         DECLARE_NAPI_FUNCTION("unitConvert", UnitConvert),
161     };
162     status = napi_define_properties(env, util,
163                                     sizeof(utilProperties) / sizeof(napi_property_descriptor),
164                                     utilProperties);
165     if (status != napi_ok) {
166         HiLog::Error(LABEL, "Failed to set properties of util at init");
167         return nullptr;
168     }
169     napi_value character = CreateCharacterObject(env);
170     if (!character) {
171         return nullptr;
172     }
173     size_t propertiesNums = 24;
174     napi_property_descriptor properties[propertiesNums];
175     CreateInitProperties(properties);
176     properties[13] = DECLARE_NAPI_PROPERTY("Util", util);  // 13 is properties index
177     properties[16] = DECLARE_NAPI_PROPERTY("Character", character);  // 16 is properties index
178     status = napi_define_properties(env, exports, propertiesNums, properties);
179     if (status != napi_ok) {
180         HiLog::Error(LABEL, "Failed to set properties at init");
181         return nullptr;
182     }
183     return exports;
184 }
185 
GetOptionValue(napi_env env,napi_value options,const std::string & optionName,std::string & value)186 void GetOptionValue(napi_env env, napi_value options, const std::string &optionName,
187     std::string &value)
188 {
189     napi_value optionValue = nullptr;
190     napi_valuetype type = napi_undefined;
191     napi_status status = napi_typeof(env, options, &type);
192     if (status != napi_ok && type != napi_object) {
193         HiLog::Error(LABEL, "Get option failed, option is not an object");
194         return;
195     }
196     bool hasProperty = false;
197     napi_status propStatus = napi_has_named_property(env, options, optionName.c_str(), &hasProperty);
198     if (propStatus == napi_ok && hasProperty) {
199         status = napi_get_named_property(env, options, optionName.c_str(), &optionValue);
200         if (status == napi_ok) {
201             size_t len;
202             napi_get_value_string_utf8(env, optionValue, nullptr, 0, &len);
203             std::vector<char> optionBuf(len + 1);
204             status = napi_get_value_string_utf8(env, optionValue, optionBuf.data(), len + 1, &len);
205             if (status != napi_ok) {
206                 HiLog::Error(LABEL, "Failed to get string item");
207                 return;
208             }
209             value = optionBuf.data();
210         }
211     }
212 }
213 
GetOptionMap(napi_env env,napi_value option,std::map<std::string,std::string> & map)214 void GetOptionMap(napi_env env, napi_value option, std::map<std::string, std::string> &map)
215 {
216     if (option != nullptr) {
217         size_t len;
218         napi_get_value_string_utf8(env, option, nullptr, 0, &len);
219         std::vector<char> styleBuf(len + 1);
220         napi_status status = napi_get_value_string_utf8(env, option, styleBuf.data(), len + 1, &len);
221         if (status != napi_ok) {
222             HiLog::Error(LABEL, "Failed to get string item");
223             return;
224         }
225         map.insert(std::make_pair("unitDisplay", styleBuf.data()));
226     }
227 }
228 
UnitConvert(napi_env env,napi_callback_info info)229 napi_value I18nAddon::UnitConvert(napi_env env, napi_callback_info info)
230 {
231     size_t argc = 5;
232     napi_value argv[5] = { 0 };
233     napi_value thisVar = nullptr;
234     void *data = nullptr;
235     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
236     std::string fromUnit;
237     GetOptionValue(env, argv[0], "unit", fromUnit);
238     std::string fromMeasSys;
239     GetOptionValue(env, argv[0], "measureSystem", fromMeasSys);
240     std::string toUnit;
241     GetOptionValue(env, argv[1], "unit", toUnit);
242     std::string toMeasSys;
243     GetOptionValue(env, argv[1], "measureSystem", toMeasSys);
244     double number = 0;
245     napi_get_value_double(env, argv[2], &number); // 2 is the index of value
246     int convertStatus = Convert(number, fromUnit, fromMeasSys, toUnit, toMeasSys);
247     size_t len;
248     napi_get_value_string_utf8(env, argv[3], nullptr, 0, &len); // 3 is the index of value
249     std::vector<char> localeBuf(len + 1);
250     // 3 is the index of value
251     status = napi_get_value_string_utf8(env, argv[3], localeBuf.data(), len + 1, &len);
252     if (status != napi_ok) {
253         HiLog::Error(LABEL, "Failed to get string item");
254         return nullptr;
255     }
256     std::vector<std::string> localeTags;
257     localeTags.push_back(localeBuf.data());
258     std::map<std::string, std::string> map = {};
259     map.insert(std::make_pair("style", "unit"));
260     if (!convertStatus) {
261         HiLog::Error(LABEL, "Do not support the conversion");
262         map.insert(std::make_pair("unit", fromUnit));
263     } else {
264         map.insert(std::make_pair("unit", toUnit));
265     }
266     // 4 is the index of value
267     GetOptionMap(env, argv[4], map);
268     std::unique_ptr<NumberFormat> numberFmt = nullptr;
269     numberFmt = std::make_unique<NumberFormat>(localeTags, map);
270     std::string value = numberFmt->Format(number);
271     napi_value result;
272     status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result);
273     if (status != napi_ok) {
274         HiLog::Error(LABEL, "Failed to create string item");
275         return nullptr;
276     }
277     return result;
278 }
279 
IsDigitAddon(napi_env env,napi_callback_info info)280 napi_value I18nAddon::IsDigitAddon(napi_env env, napi_callback_info info)
281 {
282     size_t argc = 1;
283     napi_value argv[1] = { 0 };
284     napi_value thisVar = nullptr;
285     void *data = nullptr;
286     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
287     napi_valuetype valueType = napi_valuetype::napi_undefined;
288     napi_typeof(env, argv[0], &valueType);
289     if (valueType != napi_valuetype::napi_string) {
290         napi_throw_type_error(env, nullptr, "Parameter type does not match");
291         return nullptr;
292     }
293     int32_t code = 0;
294     std::string character = GetString(env, argv[0], code);
295     if (code) {
296         return nullptr;
297     }
298     bool isDigit = IsDigit(character);
299     napi_value result = nullptr;
300     status = napi_get_boolean(env, isDigit, &result);
301     if (status != napi_ok) {
302         HiLog::Error(LABEL, "Create isDigit boolean value failed");
303         return nullptr;
304     }
305     return result;
306 }
307 
IsSpaceCharAddon(napi_env env,napi_callback_info info)308 napi_value I18nAddon::IsSpaceCharAddon(napi_env env, napi_callback_info info)
309 {
310     size_t argc = 1;
311     napi_value argv[1] = { 0 };
312     napi_value thisVar = nullptr;
313     void *data = nullptr;
314     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
315     napi_valuetype valueType = napi_valuetype::napi_undefined;
316     napi_typeof(env, argv[0], &valueType);
317     if (valueType != napi_valuetype::napi_string) {
318         napi_throw_type_error(env, nullptr, "Parameter type does not match");
319         return nullptr;
320     }
321     int32_t code = 0;
322     std::string character = GetString(env, argv[0], code);
323     if (code) {
324         return nullptr;
325     }
326     bool isSpaceChar = IsSpaceChar(character);
327     napi_value result = nullptr;
328     status = napi_get_boolean(env, isSpaceChar, &result);
329     if (status != napi_ok) {
330         HiLog::Error(LABEL, "Create isSpaceChar boolean value failed");
331         return nullptr;
332     }
333     return result;
334 }
335 
IsWhiteSpaceAddon(napi_env env,napi_callback_info info)336 napi_value I18nAddon::IsWhiteSpaceAddon(napi_env env, napi_callback_info info)
337 {
338     size_t argc = 1;
339     napi_value argv[1] = { 0 };
340     napi_value thisVar = nullptr;
341     void *data = nullptr;
342     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
343     napi_valuetype valueType = napi_valuetype::napi_undefined;
344     napi_typeof(env, argv[0], &valueType);
345     if (valueType != napi_valuetype::napi_string) {
346         napi_throw_type_error(env, nullptr, "Parameter type does not match");
347         return nullptr;
348     }
349     int32_t code = 0;
350     std::string character = GetString(env, argv[0], code);
351     if (code) {
352         return nullptr;
353     }
354     bool isWhiteSpace = IsWhiteSpace(character);
355     napi_value result = nullptr;
356     status = napi_get_boolean(env, isWhiteSpace, &result);
357     if (status != napi_ok) {
358         HiLog::Error(LABEL, "Create isWhiteSpace boolean value failed");
359         return nullptr;
360     }
361     return result;
362 }
363 
IsRTLCharacterAddon(napi_env env,napi_callback_info info)364 napi_value I18nAddon::IsRTLCharacterAddon(napi_env env, napi_callback_info info)
365 {
366     size_t argc = 1;
367     napi_value argv[1] = { 0 };
368     napi_value thisVar = nullptr;
369     void *data = nullptr;
370     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
371     napi_valuetype valueType = napi_valuetype::napi_undefined;
372     napi_typeof(env, argv[0], &valueType);
373     if (valueType != napi_valuetype::napi_string) {
374         napi_throw_type_error(env, nullptr, "Parameter type does not match");
375         return nullptr;
376     }
377     int32_t code = 0;
378     std::string character = GetString(env, argv[0], code);
379     if (code) {
380         return nullptr;
381     }
382     bool isRTLCharacter = IsRTLCharacter(character);
383     napi_value result = nullptr;
384     status = napi_get_boolean(env, isRTLCharacter, &result);
385     if (status != napi_ok) {
386         HiLog::Error(LABEL, "Create isRTLCharacter boolean value failed");
387         return nullptr;
388     }
389     return result;
390 }
391 
IsIdeoGraphicAddon(napi_env env,napi_callback_info info)392 napi_value I18nAddon::IsIdeoGraphicAddon(napi_env env, napi_callback_info info)
393 {
394     size_t argc = 1;
395     napi_value argv[1] = { 0 };
396     napi_value thisVar = nullptr;
397     void *data = nullptr;
398     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
399     napi_valuetype valueType = napi_valuetype::napi_undefined;
400     napi_typeof(env, argv[0], &valueType);
401     if (valueType != napi_valuetype::napi_string) {
402         napi_throw_type_error(env, nullptr, "Parameter type does not match");
403         return nullptr;
404     }
405     int32_t code = 0;
406     std::string character = GetString(env, argv[0], code);
407     if (code) {
408         return nullptr;
409     }
410     bool isIdeoGraphic = IsIdeoGraphic(character);
411     napi_value result = nullptr;
412     status = napi_get_boolean(env, isIdeoGraphic, &result);
413     if (status != napi_ok) {
414         HiLog::Error(LABEL, "Create isIdeoGraphic boolean value failed");
415         return nullptr;
416     }
417     return result;
418 }
419 
IsLetterAddon(napi_env env,napi_callback_info info)420 napi_value I18nAddon::IsLetterAddon(napi_env env, napi_callback_info info)
421 {
422     size_t argc = 1;
423     napi_value argv[1] = { 0 };
424     napi_value thisVar = nullptr;
425     void *data = nullptr;
426     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
427     napi_valuetype valueType = napi_valuetype::napi_undefined;
428     napi_typeof(env, argv[0], &valueType);
429     if (valueType != napi_valuetype::napi_string) {
430         napi_throw_type_error(env, nullptr, "Parameter type does not match");
431         return nullptr;
432     }
433     int32_t code = 0;
434     std::string character = GetString(env, argv[0], code);
435     if (code) {
436         return nullptr;
437     }
438     bool isLetter = IsLetter(character);
439     napi_value result = nullptr;
440     status = napi_get_boolean(env, isLetter, &result);
441     if (status != napi_ok) {
442         HiLog::Error(LABEL, "Create isLetter boolean value failed");
443         return nullptr;
444     }
445     return result;
446 }
447 
IsLowerCaseAddon(napi_env env,napi_callback_info info)448 napi_value I18nAddon::IsLowerCaseAddon(napi_env env, napi_callback_info info)
449 {
450     size_t argc = 1;
451     napi_value argv[1] = { 0 };
452     napi_value thisVar = nullptr;
453     void *data = nullptr;
454     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
455     napi_valuetype valueType = napi_valuetype::napi_undefined;
456     napi_typeof(env, argv[0], &valueType);
457     if (valueType != napi_valuetype::napi_string) {
458         napi_throw_type_error(env, nullptr, "Parameter type does not match");
459         return nullptr;
460     }
461     int32_t code = 0;
462     std::string character = GetString(env, argv[0], code);
463     if (code) {
464         return nullptr;
465     }
466     bool isLowerCase = IsLowerCase(character);
467     napi_value result = nullptr;
468     status = napi_get_boolean(env, isLowerCase, &result);
469     if (status != napi_ok) {
470         HiLog::Error(LABEL, "Create isLowerCase boolean value failed");
471         return nullptr;
472     }
473     return result;
474 }
475 
IsUpperCaseAddon(napi_env env,napi_callback_info info)476 napi_value I18nAddon::IsUpperCaseAddon(napi_env env, napi_callback_info info)
477 {
478     size_t argc = 1;
479     napi_value argv[1] = { 0 };
480     napi_value thisVar = nullptr;
481     void *data = nullptr;
482     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
483     napi_valuetype valueType = napi_valuetype::napi_undefined;
484     napi_typeof(env, argv[0], &valueType);
485     if (valueType != napi_valuetype::napi_string) {
486         napi_throw_type_error(env, nullptr, "Parameter type does not match");
487         return nullptr;
488     }
489     int32_t code = 0;
490     std::string character = GetString(env, argv[0], code);
491     if (code) {
492         return nullptr;
493     }
494     bool isUpperCase = IsUpperCase(character);
495     napi_value result = nullptr;
496     status = napi_get_boolean(env, isUpperCase, &result);
497     if (status != napi_ok) {
498         HiLog::Error(LABEL, "Create isUpperCase boolean value failed");
499         return nullptr;
500     }
501     return result;
502 }
503 
GetTypeAddon(napi_env env,napi_callback_info info)504 napi_value I18nAddon::GetTypeAddon(napi_env env, napi_callback_info info)
505 {
506     size_t argc = 1;
507     napi_value argv[1] = { 0 };
508     napi_value thisVar = nullptr;
509     void *data = nullptr;
510     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
511     napi_valuetype valueType = napi_valuetype::napi_undefined;
512     napi_typeof(env, argv[0], &valueType);
513     if (valueType != napi_valuetype::napi_string) {
514         napi_throw_type_error(env, nullptr, "Parameter type does not match");
515         return nullptr;
516     }
517     int32_t code = 0;
518     std::string character = GetString(env, argv[0], code);
519     if (code) {
520         return nullptr;
521     }
522     std::string type = GetType(character);
523     napi_value result = nullptr;
524     status = napi_create_string_utf8(env, type.c_str(), NAPI_AUTO_LENGTH, &result);
525     if (status != napi_ok) {
526         HiLog::Error(LABEL, "Create getType string value failed");
527         return nullptr;
528     }
529     return result;
530 }
531 
GetSystemLanguages(napi_env env,napi_callback_info info)532 napi_value I18nAddon::GetSystemLanguages(napi_env env, napi_callback_info info)
533 {
534     std::vector<std::string> systemLanguages;
535     LocaleConfig::GetSystemLanguages(systemLanguages);
536     napi_value result = nullptr;
537     napi_status status = napi_create_array_with_length(env, systemLanguages.size(), &result);
538     if (status != napi_ok) {
539         HiLog::Error(LABEL, "Failed to create array");
540         return nullptr;
541     }
542     for (size_t i = 0; i < systemLanguages.size(); i++) {
543         napi_value value = nullptr;
544         status = napi_create_string_utf8(env, systemLanguages[i].c_str(), NAPI_AUTO_LENGTH, &value);
545         if (status != napi_ok) {
546             HiLog::Error(LABEL, "Failed to create string item");
547             return nullptr;
548         }
549         status = napi_set_element(env, result, i, value);
550         if (status != napi_ok) {
551             HiLog::Error(LABEL, "Failed to set array item");
552             return nullptr;
553         }
554     }
555     return result;
556 }
557 
GetSystemCountries(napi_env env,napi_callback_info info)558 napi_value I18nAddon::GetSystemCountries(napi_env env, napi_callback_info info)
559 {
560     size_t argc = 1;
561     napi_value argv[1] = { 0 };
562     napi_value thisVar = nullptr;
563     void *data = nullptr;
564     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
565     size_t len = 0;
566     napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len);
567     std::vector<char> localeBuf(len + 1);
568     status = napi_get_value_string_utf8(env, argv[0], localeBuf.data(), len + 1, &len);
569     if (status != napi_ok) {
570         HiLog::Error(LABEL, "Failed to get string item");
571         return nullptr;
572     }
573     std::vector<std::string> systemCountries;
574     LocaleConfig::GetSystemCountries(systemCountries);
575     napi_value result = nullptr;
576     status = napi_create_array_with_length(env, systemCountries.size(), &result);
577     if (status != napi_ok) {
578         HiLog::Error(LABEL, "Failed to create array");
579         return nullptr;
580     }
581     for (size_t i = 0; i < systemCountries.size(); i++) {
582         napi_value value = nullptr;
583         status = napi_create_string_utf8(env, systemCountries[i].c_str(), NAPI_AUTO_LENGTH, &value);
584         if (status != napi_ok) {
585             HiLog::Error(LABEL, "Failed to create string item");
586             return nullptr;
587         }
588         status = napi_set_element(env, result, i, value);
589         if (status != napi_ok) {
590             HiLog::Error(LABEL, "Failed to set array item");
591             return nullptr;
592         }
593     }
594     return result;
595 }
596 
GetSystemLanguage(napi_env env,napi_callback_info info)597 napi_value I18nAddon::GetSystemLanguage(napi_env env, napi_callback_info info)
598 {
599     std::string value = LocaleConfig::GetSystemLanguage();
600     napi_value result = nullptr;
601     napi_status status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result);
602     if (status != napi_ok) {
603         HiLog::Error(LABEL, "Failed to create string item");
604         return nullptr;
605     }
606     return result;
607 }
608 
GetSystemRegion(napi_env env,napi_callback_info info)609 napi_value I18nAddon::GetSystemRegion(napi_env env, napi_callback_info info)
610 {
611     std::string value = LocaleConfig::GetSystemRegion();
612     napi_value result = nullptr;
613     napi_status status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result);
614     if (status != napi_ok) {
615         HiLog::Error(LABEL, "Failed to create string item");
616         return nullptr;
617     }
618     return result;
619 }
620 
GetSystemLocale(napi_env env,napi_callback_info info)621 napi_value I18nAddon::GetSystemLocale(napi_env env, napi_callback_info info)
622 {
623     std::string value = LocaleConfig::GetSystemLocale();
624     napi_value result = nullptr;
625     napi_status status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result);
626     if (status != napi_ok) {
627         HiLog::Error(LABEL, "Failed to create string item");
628         return nullptr;
629     }
630     return result;
631 }
632 
GetDisplayLanguage(napi_env env,napi_callback_info info)633 napi_value I18nAddon::GetDisplayLanguage(napi_env env, napi_callback_info info)
634 {
635     // Need to get three parameters to get the display Language.
636     size_t argc = 3;
637     napi_value argv[3] = { 0 };
638     napi_value thisVar = nullptr;
639     void *data = nullptr;
640     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
641     size_t len = 0;
642     napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len);
643     std::vector<char> localeBuf(len + 1);
644     status = napi_get_value_string_utf8(env, argv[0], localeBuf.data(), len + 1, &len);
645     if (status != napi_ok) {
646         HiLog::Error(LABEL, "Failed to get string item");
647         return nullptr;
648     }
649     napi_get_value_string_utf8(env, argv[1], nullptr, 0, &len);
650     std::vector<char> displayLocaleBuf(len + 1);
651     status = napi_get_value_string_utf8(env, argv[1], displayLocaleBuf.data(), len + 1, &len);
652     if (status != napi_ok) {
653         HiLog::Error(LABEL, "Failed to get string item");
654         return nullptr;
655     }
656     bool sentenceCase = true;
657     int sentenceCaseIndex = 2;
658     if (argv[sentenceCaseIndex] != nullptr) {
659         napi_get_value_bool(env, argv[sentenceCaseIndex], &sentenceCase);
660     }
661 
662     std::string value = LocaleConfig::GetDisplayLanguage(localeBuf.data(), displayLocaleBuf.data(), sentenceCase);
663     napi_value result = nullptr;
664     status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result);
665     if (status != napi_ok) {
666         HiLog::Error(LABEL, "Failed to create string item");
667         return nullptr;
668     }
669     return result;
670 }
671 
GetDisplayCountry(napi_env env,napi_callback_info info)672 napi_value I18nAddon::GetDisplayCountry(napi_env env, napi_callback_info info)
673 {
674     // Need to get three parameters to get the display country.
675     size_t argc = 3;
676     napi_value argv[3] = { 0 };
677     napi_value thisVar = nullptr;
678     void *data = nullptr;
679     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
680     size_t len = 0;
681     napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len);
682     std::vector<char> localeBuf(len + 1);
683     status = napi_get_value_string_utf8(env, argv[0], localeBuf.data(), len + 1, &len);
684     if (status != napi_ok) {
685         HiLog::Error(LABEL, "Failed to get string item");
686         return nullptr;
687     }
688     napi_get_value_string_utf8(env, argv[1], nullptr, 0, &len);
689     std::vector<char> displayLocaleBuf(len + 1);
690     status = napi_get_value_string_utf8(env, argv[1], displayLocaleBuf.data(), len + 1, &len);
691     if (status != napi_ok) {
692         HiLog::Error(LABEL, "Failed to get string item");
693         return nullptr;
694     }
695     bool sentenceCase = true;
696     int sentenceCaseIndex = 2;
697     if (argv[sentenceCaseIndex] != nullptr) {
698         napi_get_value_bool(env, argv[sentenceCaseIndex], &sentenceCase);
699     }
700     std::string value = LocaleConfig::GetDisplayRegion(localeBuf.data(), displayLocaleBuf.data(), sentenceCase);
701     napi_value result = nullptr;
702     status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result);
703     if (status != napi_ok) {
704         HiLog::Error(LABEL, "Failed to create string item");
705         return nullptr;
706     }
707     return result;
708 }
709 
IsSuggested(napi_env env,napi_callback_info info)710 napi_value I18nAddon::IsSuggested(napi_env env, napi_callback_info info)
711 {
712     // Need to get two parameters to check is suggested or not.
713     size_t argc = 2;
714     napi_value argv[2] = { 0 };
715     napi_value thisVar = nullptr;
716     void *data = nullptr;
717     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
718     size_t len = 0;
719     napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len);
720     std::vector<char> languageBuf(len + 1);
721     status = napi_get_value_string_utf8(env, argv[0], languageBuf.data(), len + 1, &len);
722     if (status != napi_ok) {
723         HiLog::Error(LABEL, "Failed to get string item");
724         return nullptr;
725     }
726     bool isSuggested = false;
727     if (argv[1] != nullptr) {
728         napi_get_value_string_utf8(env, argv[1], nullptr, 0, &len);
729         std::vector<char> regionBuf(len + 1);
730         status = napi_get_value_string_utf8(env, argv[1], regionBuf.data(), len + 1, &len);
731         if (status != napi_ok) {
732             HiLog::Error(LABEL, "Failed to get string item");
733             return nullptr;
734         }
735         isSuggested = LocaleConfig::IsSuggested(languageBuf.data(), regionBuf.data());
736     } else {
737         isSuggested = LocaleConfig::IsSuggested(languageBuf.data());
738     }
739     napi_value result = nullptr;
740     status = napi_get_boolean(env, isSuggested, &result);
741     if (status != napi_ok) {
742         HiLog::Error(LABEL, "Create case first boolean value failed");
743         return nullptr;
744     }
745     return result;
746 }
747 
SetSystemLanguage(napi_env env,napi_callback_info info)748 napi_value I18nAddon::SetSystemLanguage(napi_env env, napi_callback_info info)
749 {
750     size_t argc = 1;
751     napi_value argv[1] = { 0 };
752     napi_value thisVar = nullptr;
753     void *data = nullptr;
754     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
755     size_t len = 0;
756     napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len);
757     std::vector<char> languageBuf(len + 1);
758     status = napi_get_value_string_utf8(env, argv[0], languageBuf.data(), len + 1, &len);
759     if (status != napi_ok) {
760         HiLog::Error(LABEL, "Failed to get string item");
761         return nullptr;
762     }
763     bool success = LocaleConfig::SetSystemLanguage(languageBuf.data());
764     napi_value result = nullptr;
765     status = napi_get_boolean(env, success, &result);
766     if (status != napi_ok) {
767         HiLog::Error(LABEL, "Create set system language boolean value failed");
768         return nullptr;
769     }
770     return result;
771 }
772 
SetSystemRegion(napi_env env,napi_callback_info info)773 napi_value I18nAddon::SetSystemRegion(napi_env env, napi_callback_info info)
774 {
775     size_t argc = 1;
776     napi_value argv[1] = { 0 };
777     napi_value thisVar = nullptr;
778     void *data = nullptr;
779     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
780     size_t len = 0;
781     napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len);
782     std::vector<char> regionBuf(len + 1);
783     status = napi_get_value_string_utf8(env, argv[0], regionBuf.data(), len + 1, &len);
784     if (status != napi_ok) {
785         HiLog::Error(LABEL, "Failed to get string item");
786         return nullptr;
787     }
788     bool success = LocaleConfig::SetSystemRegion(regionBuf.data());
789     napi_value result = nullptr;
790     status = napi_get_boolean(env, success, &result);
791     if (status != napi_ok) {
792         HiLog::Error(LABEL, "Create set system language boolean value failed");
793         return nullptr;
794     }
795     return result;
796 }
797 
SetSystemLocale(napi_env env,napi_callback_info info)798 napi_value I18nAddon::SetSystemLocale(napi_env env, napi_callback_info info)
799 {
800     size_t argc = 1;
801     napi_value argv[1] = { 0 };
802     napi_value thisVar = nullptr;
803     void *data = nullptr;
804     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
805     size_t len = 0;
806     napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len);
807     std::vector<char> localeBuf(len + 1);
808     status = napi_get_value_string_utf8(env, argv[0], localeBuf.data(), len + 1, &len);
809     if (status != napi_ok) {
810         HiLog::Error(LABEL, "Failed to get string item");
811         return nullptr;
812     }
813     bool success = LocaleConfig::SetSystemLocale(localeBuf.data());
814     napi_value result = nullptr;
815     status = napi_get_boolean(env, success, &result);
816     if (status != napi_ok) {
817         HiLog::Error(LABEL, "Create set system language boolean value failed");
818         return nullptr;
819     }
820     return result;
821 }
822 
IsRTL(napi_env env,napi_callback_info info)823 napi_value I18nAddon::IsRTL(napi_env env, napi_callback_info info)
824 {
825     size_t argc = 1;
826     napi_value argv[1] = { 0 };
827     napi_value thisVar = nullptr;
828     void *data = nullptr;
829     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
830     size_t len = 0;
831     napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len);
832     std::vector<char> localeBuf(len + 1);
833     status = napi_get_value_string_utf8(env, argv[0], localeBuf.data(), len + 1, &len);
834     if (status != napi_ok) {
835         HiLog::Error(LABEL, "Failed to get string item");
836         return nullptr;
837     }
838     bool isRTL = LocaleConfig::IsRTL(localeBuf.data());
839     napi_value result = nullptr;
840     status = napi_get_boolean(env, isRTL, &result);
841     if (status != napi_ok) {
842         HiLog::Error(LABEL, "IsRTL failed");
843         return nullptr;
844     }
845     return result;
846 }
847 
InitPhoneNumberFormat(napi_env env,napi_value exports)848 napi_value I18nAddon::InitPhoneNumberFormat(napi_env env, napi_value exports)
849 {
850     napi_status status = napi_ok;
851     napi_property_descriptor properties[] = {
852         DECLARE_NAPI_FUNCTION("isValidNumber", IsValidPhoneNumber),
853         DECLARE_NAPI_FUNCTION("format", FormatPhoneNumber)
854     };
855 
856     napi_value constructor;
857     status = napi_define_class(env, "PhoneNumberFormat", NAPI_AUTO_LENGTH, PhoneNumberFormatConstructor, nullptr,
858                                sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor);
859     if (status != napi_ok) {
860         HiLog::Error(LABEL, "Define class failed when InitPhoneNumberFormat");
861         return nullptr;
862     }
863 
864     status = napi_set_named_property(env, exports, "PhoneNumberFormat", constructor);
865     if (status != napi_ok) {
866         HiLog::Error(LABEL, "Set property failed when InitPhoneNumberFormat");
867         return nullptr;
868     }
869     return exports;
870 }
871 
GetOptionValue(napi_env env,napi_value options,const std::string & optionName,std::map<std::string,std::string> & map)872 void GetOptionValue(napi_env env, napi_value options, const std::string &optionName,
873                     std::map<std::string, std::string> &map)
874 {
875     napi_value optionValue = nullptr;
876     napi_valuetype type = napi_undefined;
877     napi_status status = napi_typeof(env, options, &type);
878     if (status != napi_ok && type != napi_object) {
879         HiLog::Error(LABEL, "Get option failed, option is not an object");
880         return;
881     }
882     bool hasProperty = false;
883     napi_status propStatus = napi_has_named_property(env, options, optionName.c_str(), &hasProperty);
884     if (propStatus == napi_ok && hasProperty) {
885         status = napi_get_named_property(env, options, optionName.c_str(), &optionValue);
886         if (status == napi_ok) {
887             size_t len = 0;
888             napi_get_value_string_utf8(env, optionValue, nullptr, 0, &len);
889             std::vector<char> optionBuf(len + 1);
890             status = napi_get_value_string_utf8(env, optionValue, optionBuf.data(), len + 1, &len);
891             map.insert(make_pair(optionName, optionBuf.data()));
892         }
893     }
894 }
895 
PhoneNumberFormatConstructor(napi_env env,napi_callback_info info)896 napi_value I18nAddon::PhoneNumberFormatConstructor(napi_env env, napi_callback_info info)
897 {
898     size_t argc = 2;
899     napi_value argv[2] = { 0 };
900     napi_value thisVar = nullptr;
901     void *data = nullptr;
902     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
903 
904     napi_valuetype valueType = napi_valuetype::napi_undefined;
905     napi_typeof(env, argv[0], &valueType);
906     if (valueType != napi_valuetype::napi_string) {
907         napi_throw_type_error(env, nullptr, "Parameter type does not match");
908         return nullptr;
909     }
910 
911     size_t len = 0;
912     status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len);
913     if (status != napi_ok) {
914         HiLog::Error(LABEL, "Get country tag length failed");
915         return nullptr;
916     }
917 
918     std::vector<char> country (len + 1);
919     status = napi_get_value_string_utf8(env, argv[0], country.data(), len + 1, &len);
920     if (status != napi_ok) {
921         HiLog::Error(LABEL, "Get country tag failed");
922         return nullptr;
923     }
924 
925     std::map<std::string, std::string> options;
926     GetOptionValue(env, argv[1], "type", options);
927 
928     std::unique_ptr<I18nAddon> obj = nullptr;
929     obj = std::make_unique<I18nAddon>();
930     if (!obj) {
931         HiLog::Error(LABEL, "Create I18nAddon failed");
932         return nullptr;
933     }
934 
935     status = napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()),
936                        I18nAddon::Destructor, nullptr, &obj->wrapper_);
937     if (status != napi_ok) {
938         HiLog::Error(LABEL, "Wrap I18nAddon failed");
939         return nullptr;
940     }
941 
942     if (!obj->InitPhoneNumberFormatContext(env, info, country.data(), options)) {
943         return nullptr;
944     }
945 
946     obj.release();
947 
948     return thisVar;
949 }
950 
InitPhoneNumberFormatContext(napi_env env,napi_callback_info info,const std::string & country,const std::map<std::string,std::string> & options)951 bool I18nAddon::InitPhoneNumberFormatContext(napi_env env, napi_callback_info info, const std::string &country,
952                                              const std::map<std::string, std::string> &options)
953 {
954     napi_value global = nullptr;
955     napi_status status = napi_get_global(env, &global);
956     if (status != napi_ok) {
957         HiLog::Error(LABEL, "Get global failed");
958         return false;
959     }
960     env_ = env;
961     phonenumberfmt_ = std::make_unique<PhoneNumberFormat>(country, options);
962 
963     return phonenumberfmt_ != nullptr;
964 }
965 
IsValidPhoneNumber(napi_env env,napi_callback_info info)966 napi_value I18nAddon::IsValidPhoneNumber(napi_env env, napi_callback_info info)
967 {
968     size_t argc = 1;
969     napi_value argv[1] = { 0 };
970     napi_value thisVar = nullptr;
971     void *data = nullptr;
972     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
973     napi_valuetype valueType = napi_valuetype::napi_undefined;
974     napi_typeof(env, argv[0], &valueType);
975     if (valueType != napi_valuetype::napi_string) {
976         napi_throw_type_error(env, nullptr, "Parameter type does not match");
977         return nullptr;
978     }
979 
980     size_t len = 0;
981     napi_status status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len);
982     if (status != napi_ok) {
983         HiLog::Error(LABEL, "Get phone number length failed");
984         return nullptr;
985     }
986     std::vector<char> buf(len + 1);
987     status = napi_get_value_string_utf8(env, argv[0], buf.data(), len + 1, &len);
988     if (status != napi_ok) {
989         HiLog::Error(LABEL, "Get phone number failed");
990         return nullptr;
991     }
992 
993     I18nAddon *obj = nullptr;
994     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
995     if (status != napi_ok || !obj || !obj->phonenumberfmt_) {
996         HiLog::Error(LABEL, "GetPhoneNumberFormat object failed");
997         return nullptr;
998     }
999 
1000     bool isValid = obj->phonenumberfmt_->isValidPhoneNumber(buf.data());
1001 
1002     napi_value result = nullptr;
1003     status = napi_get_boolean(env, isValid, &result);
1004     if (status != napi_ok) {
1005         HiLog::Error(LABEL, "Create boolean failed");
1006         return nullptr;
1007     }
1008 
1009     return result;
1010 }
1011 
FormatPhoneNumber(napi_env env,napi_callback_info info)1012 napi_value I18nAddon::FormatPhoneNumber(napi_env env, napi_callback_info info)
1013 {
1014     size_t argc = 1;
1015     napi_value argv[1] = { 0 };
1016     napi_value thisVar = nullptr;
1017     void *data = nullptr;
1018     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1019     napi_valuetype valueType = napi_valuetype::napi_undefined;
1020     napi_typeof(env, argv[0], &valueType);
1021     if (valueType != napi_valuetype::napi_string) {
1022         napi_throw_type_error(env, nullptr, "Parameter type does not match");
1023         return nullptr;
1024     }
1025 
1026     size_t len = 0;
1027     napi_status status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len);
1028     if (status != napi_ok) {
1029         HiLog::Error(LABEL, "Get phone number length failed");
1030         return nullptr;
1031     }
1032     std::vector<char> buf(len + 1);
1033     status = napi_get_value_string_utf8(env, argv[0], buf.data(), len + 1, &len);
1034     if (status != napi_ok) {
1035         HiLog::Error(LABEL, "Get phone number failed");
1036         return nullptr;
1037     }
1038 
1039     I18nAddon *obj = nullptr;
1040     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
1041     if (status != napi_ok || !obj || !obj->phonenumberfmt_) {
1042         HiLog::Error(LABEL, "Get PhoneNumberFormat object failed");
1043         return nullptr;
1044     }
1045 
1046     std::string formattedPhoneNumber = obj->phonenumberfmt_->format(buf.data());
1047 
1048     napi_value result = nullptr;
1049     status = napi_create_string_utf8(env, formattedPhoneNumber.c_str(), NAPI_AUTO_LENGTH, &result);
1050     if (status != napi_ok) {
1051         HiLog::Error(LABEL, "Create format phone number failed");
1052         return nullptr;
1053     }
1054     return result;
1055 }
1056 
GetString(napi_env & env,napi_value & value,int32_t & code)1057 std::string I18nAddon::GetString(napi_env &env, napi_value &value, int32_t &code)
1058 {
1059     size_t len = 0;
1060     napi_status status = napi_get_value_string_utf8(env, value, nullptr, 0, &len);
1061     if (status != napi_ok) {
1062         HiLog::Error(LABEL, "Get string failed");
1063         code = 1;
1064         return "";
1065     }
1066     std::vector<char> buf(len + 1);
1067     status = napi_get_value_string_utf8(env, value, buf.data(), len + 1, &len);
1068     if (status != napi_ok) {
1069         HiLog::Error(LABEL, "Create string failed");
1070         code = 1;
1071         return "";
1072     }
1073     return buf.data();
1074 }
1075 
InitI18nCalendar(napi_env env,napi_value exports)1076 napi_value I18nAddon::InitI18nCalendar(napi_env env, napi_value exports)
1077 {
1078     napi_status status = napi_ok;
1079     napi_property_descriptor properties[] = {
1080         DECLARE_NAPI_FUNCTION("setTime", SetTime),
1081         DECLARE_NAPI_FUNCTION("set", Set),
1082         DECLARE_NAPI_FUNCTION("getTimeZone", GetTimeZone),
1083         DECLARE_NAPI_FUNCTION("setTimeZone", SetTimeZone),
1084         DECLARE_NAPI_FUNCTION("getFirstDayOfWeek", GetFirstDayOfWeek),
1085         DECLARE_NAPI_FUNCTION("setFirstDayOfWeek", SetFirstDayOfWeek),
1086         DECLARE_NAPI_FUNCTION("getMinimalDaysInFirstWeek", GetMinimalDaysInFirstWeek),
1087         DECLARE_NAPI_FUNCTION("setMinimalDaysInFirstWeek", SetMinimalDaysInFirstWeek),
1088         DECLARE_NAPI_FUNCTION("get", Get),
1089         DECLARE_NAPI_FUNCTION("getDisplayName", GetDisplayName),
1090         DECLARE_NAPI_FUNCTION("isWeekend", IsWeekend)
1091     };
1092     napi_value constructor = nullptr;
1093     status = napi_define_class(env, "I18nCalendar", NAPI_AUTO_LENGTH, CalendarConstructor, nullptr,
1094         sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor);
1095     if (status != napi_ok) {
1096         HiLog::Error(LABEL, "Failed to define class at Init");
1097         return nullptr;
1098     }
1099     g_constructor = new (std::nothrow) napi_ref;
1100     if (!g_constructor) {
1101         HiLog::Error(LABEL, "Failed to create ref at init");
1102         return nullptr;
1103     }
1104     status = napi_create_reference(env, constructor, 1, g_constructor);
1105     if (status != napi_ok) {
1106         HiLog::Error(LABEL, "Failed to create reference at init");
1107         return nullptr;
1108     }
1109     return exports;
1110 }
1111 
CalendarConstructor(napi_env env,napi_callback_info info)1112 napi_value I18nAddon::CalendarConstructor(napi_env env, napi_callback_info info)
1113 {
1114     size_t argc = 2;
1115     napi_value argv[2] = { 0 };
1116     argv[0] = nullptr;
1117     argv[1] = nullptr;
1118     napi_value thisVar = nullptr;
1119     void *data = nullptr;
1120     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1121     if (status != napi_ok) {
1122         return nullptr;
1123     }
1124     napi_valuetype valueType = napi_valuetype::napi_undefined;
1125     napi_typeof(env, argv[0], &valueType);
1126     if (valueType != napi_valuetype::napi_string) {
1127         napi_throw_type_error(env, nullptr, "Parameter type does not match");
1128         return nullptr;
1129     }
1130     int32_t code = 0;
1131     std::string localeTag = GetString(env, argv[0], code);
1132     if (code) {
1133         return nullptr;
1134     }
1135     CalendarType type = GetCalendarType(env, argv[1]);
1136     std::unique_ptr<I18nAddon> obj = nullptr;
1137     obj = std::make_unique<I18nAddon>();
1138     if (!obj) {
1139         HiLog::Error(LABEL, "Create I18nAddon failed");
1140         return nullptr;
1141     }
1142     status =
1143         napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()), I18nAddon::Destructor, nullptr, &obj->wrapper_);
1144     if (status != napi_ok) {
1145         HiLog::Error(LABEL, "Wrap II18nAddon failed");
1146         return nullptr;
1147     }
1148     if (!obj->InitCalendarContext(env, info, localeTag, type)) {
1149         return nullptr;
1150     }
1151     obj.release();
1152     return thisVar;
1153 }
1154 
GetCalendarType(napi_env env,napi_value value)1155 CalendarType I18nAddon::GetCalendarType(napi_env env, napi_value value)
1156 {
1157     CalendarType type = CalendarType::UNDEFINED;
1158     if (value != nullptr) {
1159         napi_valuetype valueType = napi_valuetype::napi_undefined;
1160         napi_typeof(env, value, &valueType);
1161         if (valueType != napi_valuetype::napi_string) {
1162             napi_throw_type_error(env, nullptr, "Parameter type does not match");
1163             return type;
1164         }
1165         int32_t code = 0;
1166         std::string calendarType = GetString(env, value, code);
1167         if (code) {
1168             return type;
1169         }
1170         if (g_typeMap.find(calendarType) != g_typeMap.end()) {
1171             type = g_typeMap[calendarType];
1172         }
1173     }
1174     return type;
1175 }
1176 
InitCalendarContext(napi_env env,napi_callback_info info,const std::string & localeTag,CalendarType type)1177 bool I18nAddon::InitCalendarContext(napi_env env, napi_callback_info info, const std::string &localeTag,
1178     CalendarType type)
1179 {
1180     calendar_ = std::make_unique<I18nCalendar>(localeTag, type);
1181     return calendar_ != nullptr;
1182 }
1183 
GetCalendar(napi_env env,napi_callback_info info)1184 napi_value I18nAddon::GetCalendar(napi_env env, napi_callback_info info)
1185 {
1186     size_t argc = 2; // retrieve 2 arguments
1187     napi_value argv[2] = { 0 };
1188     argv[0] = nullptr;
1189     argv[1] = nullptr;
1190     napi_value thisVar = nullptr;
1191     void *data = nullptr;
1192     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1193     napi_value constructor = nullptr;
1194     napi_status status = napi_get_reference_value(env, *g_constructor, &constructor);
1195     if (status != napi_ok) {
1196         HiLog::Error(LABEL, "Failed to create reference at GetCalendar");
1197         return nullptr;
1198     }
1199     if (!argv[1]) {
1200         status = napi_create_string_utf8(env, "", NAPI_AUTO_LENGTH, argv + 1);
1201         if (status != napi_ok) {
1202             return nullptr;
1203         }
1204     }
1205     napi_value result = nullptr;
1206     status = napi_new_instance(env, constructor, 2, argv, &result); // 2 arguments
1207     if (status != napi_ok) {
1208         HiLog::Error(LABEL, "Get calendar create instance failed");
1209         return nullptr;
1210     }
1211     return result;
1212 }
1213 
GetDate(napi_env env,napi_value value)1214 napi_value I18nAddon::GetDate(napi_env env, napi_value value)
1215 {
1216     if (!value) {
1217         return nullptr;
1218     }
1219     napi_value funcGetDateInfo = nullptr;
1220     napi_status status = napi_get_named_property(env, value, "valueOf", &funcGetDateInfo);
1221     if (status != napi_ok) {
1222         HiLog::Error(LABEL, "Get method valueOf failed");
1223         return nullptr;
1224     }
1225     napi_value ret_value = nullptr;
1226     status = napi_call_function(env, value, funcGetDateInfo, 0, nullptr, &ret_value);
1227     if (status != napi_ok) {
1228         HiLog::Error(LABEL, "Get milliseconds failed");
1229         return nullptr;
1230     }
1231     return ret_value;
1232 }
1233 
SetMilliseconds(napi_env env,napi_value value)1234 void I18nAddon::SetMilliseconds(napi_env env, napi_value value)
1235 {
1236     if (!value) {
1237         return;
1238     }
1239     double milliseconds = 0;
1240     napi_valuetype valueType = napi_valuetype::napi_undefined;
1241     napi_typeof(env, value, &valueType);
1242     if (valueType != napi_valuetype::napi_number) {
1243         napi_throw_type_error(env, nullptr, "Parameter type does not match");
1244         return;
1245     }
1246     napi_status status = napi_get_value_double(env, value, &milliseconds);
1247     if (status != napi_ok) {
1248         HiLog::Error(LABEL, "Retrieve milliseconds failed");
1249         return;
1250     }
1251     if (calendar_ != nullptr) {
1252         calendar_->SetTime(milliseconds);
1253     }
1254 }
1255 
Set(napi_env env,napi_callback_info info)1256 napi_value I18nAddon::Set(napi_env env, napi_callback_info info)
1257 {
1258     size_t argc = 6; // Set may have 6 arguments
1259     napi_value argv[6] = { 0 };
1260     for (size_t i = 0; i < argc; ++i) {
1261         argv[i] = nullptr;
1262     }
1263     napi_value thisVar = nullptr;
1264     void *data = nullptr;
1265     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1266     napi_valuetype valueType = napi_valuetype::napi_undefined;
1267     napi_status status = napi_ok;
1268     int32_t times[3] = { 0 }; // There are at least 3 arguments.
1269     for (int i = 0; i < 3; ++i) { // There are at least 3 arguments.
1270         napi_typeof(env, argv[i], &valueType);
1271         if (valueType != napi_valuetype::napi_number) {
1272             napi_throw_type_error(env, nullptr, "Parameter type does not match");
1273             return nullptr;
1274         }
1275         status = napi_get_value_int32(env, argv[i], times + i);
1276         if (status != napi_ok) {
1277             HiLog::Error(LABEL, "Retrieve time value failed");
1278             return nullptr;
1279         }
1280     }
1281     I18nAddon *obj = nullptr;
1282     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
1283     if (status != napi_ok || !obj || !obj->calendar_) {
1284         HiLog::Error(LABEL, "Get calendar object failed");
1285         return nullptr;
1286     }
1287     obj->calendar_->Set(times[0], times[1], times[2]); // 2 is the index of date
1288     obj->SetField(env, argv[3], UCalendarDateFields::UCAL_HOUR_OF_DAY); // 3 is the index of hour
1289     obj->SetField(env, argv[4], UCalendarDateFields::UCAL_MINUTE); // 4 is the index of minute
1290     obj->SetField(env, argv[5], UCalendarDateFields::UCAL_SECOND); // 5 is the index of second
1291     return nullptr;
1292 }
1293 
SetTime(napi_env env,napi_callback_info info)1294 napi_value I18nAddon::SetTime(napi_env env, napi_callback_info info)
1295 {
1296     size_t argc = 1;
1297     napi_value argv[1] = { 0 };
1298     argv[0] = nullptr;
1299     napi_value thisVar = nullptr;
1300     void *data = nullptr;
1301     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1302     if (!argv[0]) {
1303         return nullptr;
1304     }
1305     I18nAddon *obj = nullptr;
1306     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
1307     if (status != napi_ok || !obj || !obj->calendar_) {
1308         HiLog::Error(LABEL, "Get calendar object failed");
1309         return nullptr;
1310     }
1311     napi_valuetype type = napi_valuetype::napi_undefined;
1312     status = napi_typeof(env, argv[0], &type);
1313     if (status != napi_ok) {
1314         return nullptr;
1315     }
1316     if (type == napi_valuetype::napi_number) {
1317         obj->SetMilliseconds(env, argv[0]);
1318         return nullptr;
1319     } else {
1320         napi_value val = GetDate(env, argv[0]);
1321         if (!val) {
1322             return nullptr;
1323         }
1324         obj->SetMilliseconds(env, val);
1325         return nullptr;
1326     }
1327 }
1328 
SetField(napi_env env,napi_value value,UCalendarDateFields field)1329 void I18nAddon::SetField(napi_env env, napi_value value, UCalendarDateFields field)
1330 {
1331     if (!value) {
1332         return;
1333     }
1334     int32_t val = 0;
1335     napi_valuetype valueType = napi_valuetype::napi_undefined;
1336     napi_typeof(env, value, &valueType);
1337     if (valueType != napi_valuetype::napi_number) {
1338         napi_throw_type_error(env, nullptr, "Parameter type does not match");
1339         return;
1340     }
1341     napi_status status = napi_get_value_int32(env, value, &val);
1342     if (status != napi_ok) {
1343         HiLog::Error(LABEL, "Retrieve field failed");
1344         return;
1345     }
1346     if (calendar_ != nullptr) {
1347         calendar_->Set(field, val);
1348     }
1349 }
1350 
SetTimeZone(napi_env env,napi_callback_info info)1351 napi_value I18nAddon::SetTimeZone(napi_env env, napi_callback_info info)
1352 {
1353     size_t argc = 1;
1354     napi_value argv[1] = { 0 };
1355     argv[0] = nullptr;
1356     napi_value thisVar = nullptr;
1357     void *data = nullptr;
1358     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1359     napi_valuetype valueType = napi_valuetype::napi_undefined;
1360     napi_typeof(env, argv[0], &valueType);
1361     if (valueType != napi_valuetype::napi_string) {
1362         napi_throw_type_error(env, nullptr, "Parameter type does not match");
1363         return nullptr;
1364     }
1365     size_t len = 0;
1366     napi_status status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len);
1367     if (status != napi_ok) {
1368         HiLog::Error(LABEL, "Get timezone length failed");
1369         return nullptr;
1370     }
1371     std::vector<char> buf(len + 1);
1372     status = napi_get_value_string_utf8(env, argv[0], buf.data(), len + 1, &len);
1373     if (status != napi_ok) {
1374         HiLog::Error(LABEL, "Get timezone failed");
1375         return nullptr;
1376     }
1377     std::string timezone(buf.data());
1378     I18nAddon *obj = nullptr;
1379     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
1380     if (status != napi_ok || !obj || !obj->calendar_) {
1381         HiLog::Error(LABEL, "Get calendar object failed");
1382         return nullptr;
1383     }
1384     obj->calendar_->SetTimeZone(timezone);
1385     return nullptr;
1386 }
1387 
GetTimeZone(napi_env env,napi_callback_info info)1388 napi_value I18nAddon::GetTimeZone(napi_env env, napi_callback_info info)
1389 {
1390     size_t argc = 0;
1391     napi_value *argv = nullptr;
1392     napi_value thisVar = nullptr;
1393     void *data = nullptr;
1394     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1395     I18nAddon *obj = nullptr;
1396     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
1397     if (status != napi_ok || !obj || !obj->calendar_) {
1398         HiLog::Error(LABEL, "Get calendar object failed");
1399         return nullptr;
1400     }
1401     std::string temp = obj->calendar_->GetTimeZone();
1402     napi_value result = nullptr;
1403     status = napi_create_string_utf8(env, temp.c_str(), NAPI_AUTO_LENGTH, &result);
1404     if (status != napi_ok) {
1405         HiLog::Error(LABEL, "Create timezone string failed");
1406         return nullptr;
1407     }
1408     return result;
1409 }
1410 
GetFirstDayOfWeek(napi_env env,napi_callback_info info)1411 napi_value I18nAddon::GetFirstDayOfWeek(napi_env env, napi_callback_info info)
1412 {
1413     size_t argc = 0;
1414     napi_value *argv = nullptr;
1415     napi_value thisVar = nullptr;
1416     void *data = nullptr;
1417     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1418     I18nAddon *obj = nullptr;
1419     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
1420     if (status != napi_ok || !obj || !obj->calendar_) {
1421         HiLog::Error(LABEL, "Get calendar object failed");
1422         return nullptr;
1423     }
1424     int32_t temp = obj->calendar_->GetFirstDayOfWeek();
1425     napi_value result = nullptr;
1426     status = napi_create_int32(env, temp, &result);
1427     if (status != napi_ok) {
1428         HiLog::Error(LABEL, "Create int32 failed");
1429         return nullptr;
1430     }
1431     return result;
1432 }
1433 
GetMinimalDaysInFirstWeek(napi_env env,napi_callback_info info)1434 napi_value I18nAddon::GetMinimalDaysInFirstWeek(napi_env env, napi_callback_info info)
1435 {
1436     size_t argc = 0;
1437     napi_value *argv = nullptr;
1438     napi_value thisVar = nullptr;
1439     void *data = nullptr;
1440     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1441     I18nAddon *obj = nullptr;
1442     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
1443     if (status != napi_ok || !obj || !obj->calendar_) {
1444         HiLog::Error(LABEL, "Get calendar object failed");
1445         return nullptr;
1446     }
1447     int32_t temp = obj->calendar_->GetMinimalDaysInFirstWeek();
1448     napi_value result = nullptr;
1449     status = napi_create_int32(env, temp, &result);
1450     if (status != napi_ok) {
1451         HiLog::Error(LABEL, "Create int32 failed");
1452         return nullptr;
1453     }
1454     return result;
1455 }
1456 
SetFirstDayOfWeek(napi_env env,napi_callback_info info)1457 napi_value I18nAddon::SetFirstDayOfWeek(napi_env env, napi_callback_info info)
1458 {
1459     size_t argc = 1;
1460     napi_value argv[1] = { 0 };
1461     argv[0] = nullptr;
1462     napi_value thisVar = nullptr;
1463     void *data = nullptr;
1464     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1465     napi_valuetype valueType = napi_valuetype::napi_undefined;
1466     napi_typeof(env, argv[0], &valueType);
1467     if (valueType != napi_valuetype::napi_number) {
1468         napi_throw_type_error(env, nullptr, "Parameter type does not match");
1469         return nullptr;
1470     }
1471     int32_t value = 0;
1472     napi_status status = napi_get_value_int32(env, argv[0], &value);
1473     if (status != napi_ok) {
1474         HiLog::Error(LABEL, "Get int32 failed");
1475         return nullptr;
1476     }
1477     I18nAddon *obj = nullptr;
1478     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
1479     if (status != napi_ok || !obj || !obj->calendar_) {
1480         HiLog::Error(LABEL, "Get calendar object failed");
1481         return nullptr;
1482     }
1483     obj->calendar_->SetFirstDayOfWeek(value);
1484     return nullptr;
1485 }
1486 
SetMinimalDaysInFirstWeek(napi_env env,napi_callback_info info)1487 napi_value I18nAddon::SetMinimalDaysInFirstWeek(napi_env env, napi_callback_info info)
1488 {
1489     size_t argc = 1;
1490     napi_value argv[1] = { 0 };
1491     argv[0] = nullptr;
1492     napi_value thisVar = nullptr;
1493     void *data = nullptr;
1494     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1495     napi_valuetype valueType = napi_valuetype::napi_undefined;
1496     napi_typeof(env, argv[0], &valueType);
1497     if (valueType != napi_valuetype::napi_number) {
1498         napi_throw_type_error(env, nullptr, "Parameter type does not match");
1499         return nullptr;
1500     }
1501     int32_t value = 0;
1502     napi_status status = napi_get_value_int32(env, argv[0], &value);
1503     if (status != napi_ok) {
1504         HiLog::Error(LABEL, "Get int32 failed");
1505         return nullptr;
1506     }
1507     I18nAddon *obj = nullptr;
1508     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
1509     if (status != napi_ok || !obj || !obj->calendar_) {
1510         HiLog::Error(LABEL, "Get calendar object failed");
1511         return nullptr;
1512     }
1513     obj->calendar_->SetMinimalDaysInFirstWeek(value);
1514     return nullptr;
1515 }
1516 
Get(napi_env env,napi_callback_info info)1517 napi_value I18nAddon::Get(napi_env env, napi_callback_info info)
1518 {
1519     size_t argc = 1;
1520     napi_value argv[1] = { 0 };
1521     argv[0] = nullptr;
1522     napi_value thisVar = nullptr;
1523     void *data = nullptr;
1524     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1525     napi_valuetype valueType = napi_valuetype::napi_undefined;
1526     napi_typeof(env, argv[0], &valueType);
1527     if (valueType != napi_valuetype::napi_string) {
1528         napi_throw_type_error(env, nullptr, "Parameter type does not match");
1529         return nullptr;
1530     }
1531     size_t len = 0;
1532     napi_status status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len);
1533     if (status != napi_ok) {
1534         HiLog::Error(LABEL, "Get field length failed");
1535         return nullptr;
1536     }
1537     std::vector<char> buf(len + 1);
1538     status = napi_get_value_string_utf8(env, argv[0], buf.data(), len + 1, &len);
1539     if (status != napi_ok) {
1540         HiLog::Error(LABEL, "Get field failed");
1541         return nullptr;
1542     }
1543     std::string field(buf.data());
1544     if (g_fieldsMap.find(field) == g_fieldsMap.end()) {
1545         HiLog::Error(LABEL, "Invalid field");
1546         return nullptr;
1547     }
1548     I18nAddon *obj = nullptr;
1549     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
1550     if (status != napi_ok || !obj || !obj->calendar_) {
1551         HiLog::Error(LABEL, "Get calendar object failed");
1552         return nullptr;
1553     }
1554     int32_t value = obj->calendar_->Get(g_fieldsMap[field]);
1555     napi_value result = nullptr;
1556     status = napi_create_int32(env, value, &result);
1557     if (status != napi_ok) {
1558         HiLog::Error(LABEL, "Create int32 failed");
1559         return nullptr;
1560     }
1561     return result;
1562 }
1563 
IsWeekend(napi_env env,napi_callback_info info)1564 napi_value I18nAddon::IsWeekend(napi_env env, napi_callback_info info)
1565 {
1566     size_t argc = 1;
1567     napi_value argv[1] = { 0 };
1568     argv[0] = nullptr;
1569     napi_value thisVar = nullptr;
1570     void *data = nullptr;
1571     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1572     I18nAddon *obj = nullptr;
1573     bool isWeekEnd = false;
1574     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
1575     do {
1576         if (status != napi_ok || !obj || !obj->calendar_) {
1577             HiLog::Error(LABEL, "Get calendar object failed");
1578             break;
1579         }
1580         if (!argv[0]) {
1581             isWeekEnd = obj->calendar_->IsWeekend();
1582         } else {
1583             napi_value funcGetDateInfo = nullptr;
1584             status = napi_get_named_property(env, argv[0], "valueOf", &funcGetDateInfo);
1585             if (status != napi_ok) {
1586                 HiLog::Error(LABEL, "Get method now failed");
1587                 break;
1588             }
1589             napi_value value = nullptr;
1590             status = napi_call_function(env, argv[0], funcGetDateInfo, 0, nullptr, &value);
1591             if (status != napi_ok) {
1592                 HiLog::Error(LABEL, "Get milliseconds failed");
1593                 break;
1594             }
1595             double milliseconds = 0;
1596             status = napi_get_value_double(env, value, &milliseconds);
1597             if (status != napi_ok) {
1598                 HiLog::Error(LABEL, "Retrieve milliseconds failed");
1599                 break;
1600             }
1601             UErrorCode error = U_ZERO_ERROR;
1602             isWeekEnd = obj->calendar_->IsWeekend(milliseconds, error);
1603         }
1604     } while (false);
1605     napi_value result = nullptr;
1606     status = napi_get_boolean(env, isWeekEnd, &result);
1607     if (status != napi_ok) {
1608         HiLog::Error(LABEL, "Create boolean failed");
1609         return nullptr;
1610     }
1611     return result;
1612 }
1613 
GetDisplayName(napi_env env,napi_callback_info info)1614 napi_value I18nAddon::GetDisplayName(napi_env env, napi_callback_info info)
1615 {
1616     size_t argc = 1;
1617     napi_value argv[1] = { 0 };
1618     argv[0] = nullptr;
1619     napi_value thisVar = nullptr;
1620     void *data = nullptr;
1621     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1622     napi_valuetype valueType = napi_valuetype::napi_undefined;
1623     napi_typeof(env, argv[0], &valueType);
1624     if (valueType != napi_valuetype::napi_string) {
1625         napi_throw_type_error(env, nullptr, "Parameter type does not match");
1626         return nullptr;
1627     }
1628     int32_t code = 0;
1629     std::string localeTag = GetString(env, argv[0], code);
1630     if (code) {
1631         return nullptr;
1632     }
1633     I18nAddon *obj = nullptr;
1634     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
1635     if (status != napi_ok || !obj || !obj->calendar_) {
1636         HiLog::Error(LABEL, "Get calendar object failed");
1637         return nullptr;
1638     }
1639     if (!obj->calendar_) {
1640         return nullptr;
1641     }
1642     std::string name = obj->calendar_->GetDisplayName(localeTag);
1643     napi_value result = nullptr;
1644     status = napi_create_string_utf8(env, name.c_str(), NAPI_AUTO_LENGTH, &result);
1645     if (status != napi_ok) {
1646         HiLog::Error(LABEL, "Create calendar name string failed");
1647         return nullptr;
1648     }
1649     return result;
1650 }
1651 
InitIndexUtil(napi_env env,napi_value exports)1652 napi_value I18nAddon::InitIndexUtil(napi_env env, napi_value exports)
1653 {
1654     napi_property_descriptor properties[] = {
1655         DECLARE_NAPI_FUNCTION("getIndexList", GetIndexList),
1656         DECLARE_NAPI_FUNCTION("addLocale", AddLocale),
1657         DECLARE_NAPI_FUNCTION("getIndex", GetIndex)
1658     };
1659 
1660     napi_value constructor = nullptr;
1661     napi_status status = napi_define_class(env, "IndexUtil", NAPI_AUTO_LENGTH, IndexUtilConstructor, nullptr,
1662         sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor);
1663     if (status != napi_ok) {
1664         HiLog::Error(LABEL, "Define class failed when InitPhoneNumberFormat");
1665         return nullptr;
1666     }
1667 
1668     status = napi_create_reference(env, constructor, 1, &g_indexUtilConstructor);
1669     if (status != napi_ok) {
1670         HiLog::Error(LABEL, "Failed to create reference at init");
1671         return nullptr;
1672     }
1673     return exports;
1674 }
1675 
BreakIteratorConstructor(napi_env env,napi_callback_info info)1676 napi_value I18nAddon::BreakIteratorConstructor(napi_env env, napi_callback_info info)
1677 {
1678     size_t argc = 1;
1679     napi_value argv[1] = { nullptr };
1680     napi_value thisVar = nullptr;
1681     void *data = nullptr;
1682     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1683     if (status != napi_ok) {
1684         return nullptr;
1685     }
1686     napi_valuetype valueType = napi_valuetype::napi_undefined;
1687     napi_typeof(env, argv[0], &valueType);
1688     if (valueType != napi_valuetype::napi_string) {
1689         napi_throw_type_error(env, nullptr, "Parameter type does not match");
1690         return nullptr;
1691     }
1692     int32_t code = 0;
1693     std::string localeTag = GetString(env, argv[0], code);
1694     if (code) {
1695         return nullptr;
1696     }
1697     std::unique_ptr<I18nAddon> obj = nullptr;
1698     obj = std::make_unique<I18nAddon>();
1699     if (!obj) {
1700         HiLog::Error(LABEL, "Create I18nAddon failed");
1701         return nullptr;
1702     }
1703     status =
1704         napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()), I18nAddon::Destructor, nullptr, &obj->wrapper_);
1705     if (status != napi_ok) {
1706         HiLog::Error(LABEL, "Wrap II18nAddon failed");
1707         return nullptr;
1708     }
1709     obj->brkiter_ = std::make_unique<I18nBreakIterator>(localeTag);
1710     if (!obj->brkiter_) {
1711         HiLog::Error(LABEL, "Wrap BreakIterator failed");
1712         return nullptr;
1713     }
1714     obj.release();
1715     return thisVar;
1716 }
1717 
InitBreakIterator(napi_env env,napi_value exports)1718 napi_value I18nAddon::InitBreakIterator(napi_env env, napi_value exports)
1719 {
1720     napi_status status = napi_ok;
1721     napi_property_descriptor properties[] = {
1722         DECLARE_NAPI_FUNCTION("current", Current),
1723         DECLARE_NAPI_FUNCTION("first", First),
1724         DECLARE_NAPI_FUNCTION("last", Last),
1725         DECLARE_NAPI_FUNCTION("next", Next),
1726         DECLARE_NAPI_FUNCTION("previous", Previous),
1727         DECLARE_NAPI_FUNCTION("setLineBreakText", SetText),
1728         DECLARE_NAPI_FUNCTION("following", Following),
1729         DECLARE_NAPI_FUNCTION("getLineBreakText", GetText),
1730         DECLARE_NAPI_FUNCTION("isBoundary", IsBoundary),
1731     };
1732     napi_value constructor = nullptr;
1733     status = napi_define_class(env, "BreakIterator", NAPI_AUTO_LENGTH, BreakIteratorConstructor, nullptr,
1734         sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor);
1735     if (status != napi_ok) {
1736         HiLog::Error(LABEL, "Failed to define class BreakIterator at Init");
1737         return nullptr;
1738     }
1739     g_brkConstructor = new (std::nothrow) napi_ref;
1740     if (!g_brkConstructor) {
1741         HiLog::Error(LABEL, "Failed to create brkiterator ref at init");
1742         return nullptr;
1743     }
1744     status = napi_create_reference(env, constructor, 1, g_brkConstructor);
1745     if (status != napi_ok) {
1746         HiLog::Error(LABEL, "Failed to create reference g_brkConstructor at init");
1747         return nullptr;
1748     }
1749     return exports;
1750 }
1751 
GetLineInstance(napi_env env,napi_callback_info info)1752 napi_value I18nAddon::GetLineInstance(napi_env env, napi_callback_info info)
1753 {
1754     size_t argc = 1;
1755     napi_value argv[1] = { nullptr };
1756     napi_value thisVar = nullptr;
1757     void *data = nullptr;
1758     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1759     napi_value constructor = nullptr;
1760     napi_status status = napi_get_reference_value(env, *g_brkConstructor, &constructor);
1761     if (status != napi_ok) {
1762         HiLog::Error(LABEL, "Failed to create reference at GetLineInstance");
1763         return nullptr;
1764     }
1765     if (!argv[0]) {
1766         return nullptr;
1767     }
1768     napi_value result = nullptr;
1769     status = napi_new_instance(env, constructor, 1, argv, &result); // 1 arguments
1770     if (status != napi_ok) {
1771         HiLog::Error(LABEL, "GetLineInstance create instance failed");
1772         return nullptr;
1773     }
1774     return result;
1775 }
1776 
Current(napi_env env,napi_callback_info info)1777 napi_value I18nAddon::Current(napi_env env, napi_callback_info info)
1778 {
1779     size_t argc = 0;
1780     napi_value *argv = nullptr;
1781     napi_value thisVar = nullptr;
1782     void *data = nullptr;
1783     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1784     I18nAddon *obj = nullptr;
1785     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
1786     if (status != napi_ok || !obj || !obj->brkiter_) {
1787         HiLog::Error(LABEL, "Get BreakIterator object failed");
1788         return nullptr;
1789     }
1790     int value = obj->brkiter_->current();
1791     napi_value result = nullptr;
1792     status = napi_create_int32(env, value, &result);
1793     if (status != napi_ok) {
1794         HiLog::Error(LABEL, "Create int32_t value failed");
1795         return nullptr;
1796     }
1797     return result;
1798 }
1799 
First(napi_env env,napi_callback_info info)1800 napi_value I18nAddon::First(napi_env env, napi_callback_info info)
1801 {
1802     size_t argc = 0;
1803     napi_value *argv = nullptr;
1804     napi_value thisVar = nullptr;
1805     void *data = nullptr;
1806     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1807     I18nAddon *obj = nullptr;
1808     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
1809     if (status != napi_ok || !obj || !obj->brkiter_) {
1810         HiLog::Error(LABEL, "Get BreakIterator object failed");
1811         return nullptr;
1812     }
1813     int value = obj->brkiter_->first();
1814     napi_value result = nullptr;
1815     status = napi_create_int32(env, value, &result);
1816     if (status != napi_ok) {
1817         HiLog::Error(LABEL, "Create int32_t value failed");
1818         return nullptr;
1819     }
1820     return result;
1821 }
1822 
Last(napi_env env,napi_callback_info info)1823 napi_value I18nAddon::Last(napi_env env, napi_callback_info info)
1824 {
1825     size_t argc = 0;
1826     napi_value *argv = nullptr;
1827     napi_value thisVar = nullptr;
1828     void *data = nullptr;
1829     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1830     I18nAddon *obj = nullptr;
1831     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
1832     if (status != napi_ok || !obj || !obj->brkiter_) {
1833         HiLog::Error(LABEL, "Get BreakIterator object failed");
1834         return nullptr;
1835     }
1836     int value = obj->brkiter_->last();
1837     napi_value result = nullptr;
1838     status = napi_create_int32(env, value, &result);
1839     if (status != napi_ok) {
1840         HiLog::Error(LABEL, "Create int32_t value failed");
1841         return nullptr;
1842     }
1843     return result;
1844 }
1845 
Previous(napi_env env,napi_callback_info info)1846 napi_value I18nAddon::Previous(napi_env env, napi_callback_info info)
1847 {
1848     size_t argc = 0;
1849     napi_value *argv = nullptr;
1850     napi_value thisVar = nullptr;
1851     void *data = nullptr;
1852     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1853     I18nAddon *obj = nullptr;
1854     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
1855     if (status != napi_ok || !obj || !obj->brkiter_) {
1856         HiLog::Error(LABEL, "Get BreakIterator object failed");
1857         return nullptr;
1858     }
1859     int value = obj->brkiter_->previous();
1860     napi_value result = nullptr;
1861     status = napi_create_int32(env, value, &result);
1862     if (status != napi_ok) {
1863         HiLog::Error(LABEL, "Create int32_t value failed");
1864         return nullptr;
1865     }
1866     return result;
1867 }
1868 
Next(napi_env env,napi_callback_info info)1869 napi_value I18nAddon::Next(napi_env env, napi_callback_info info)
1870 {
1871     size_t argc = 1;
1872     napi_value argv[1] = { nullptr };
1873     napi_value thisVar = nullptr;
1874     void *data = nullptr;
1875     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1876     I18nAddon *obj = nullptr;
1877     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
1878     if (status != napi_ok || !obj || !obj->brkiter_) {
1879         HiLog::Error(LABEL, "Get BreakIterator object failed");
1880         return nullptr;
1881     }
1882     int value = 1;
1883     if (argv[0] != nullptr) {
1884         napi_valuetype valueType = napi_valuetype::napi_undefined;
1885         napi_typeof(env, argv[0], &valueType);
1886         if (valueType != napi_valuetype::napi_number) {
1887             napi_throw_type_error(env, nullptr, "Parameter type does not match");
1888             return nullptr;
1889         }
1890         status = napi_get_value_int32(env, argv[0], &value);
1891         if (status != napi_ok) {
1892             HiLog::Error(LABEL, "Retrieve next value failed");
1893             return nullptr;
1894         }
1895     }
1896     value = obj->brkiter_->next(value);
1897     napi_value result = nullptr;
1898     status = napi_create_int32(env, value, &result);
1899     if (status != napi_ok) {
1900         HiLog::Error(LABEL, "Create int32_t value failed");
1901         return nullptr;
1902     }
1903     return result;
1904 }
1905 
SetText(napi_env env,napi_callback_info info)1906 napi_value I18nAddon::SetText(napi_env env, napi_callback_info info)
1907 {
1908     size_t argc = 1;
1909     napi_value argv[1] = { nullptr };
1910     napi_value thisVar = nullptr;
1911     void *data = nullptr;
1912     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1913     I18nAddon *obj = nullptr;
1914     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
1915     if (status != napi_ok || !obj || !obj->brkiter_) {
1916         HiLog::Error(LABEL, "Get BreakIterator object failed");
1917         return nullptr;
1918     }
1919     if (!argv[0]) {
1920         return nullptr;
1921     }
1922     napi_valuetype valueType = napi_valuetype::napi_undefined;
1923     napi_typeof(env, argv[0], &valueType);
1924     if (valueType != napi_valuetype::napi_string) {
1925         napi_throw_type_error(env, nullptr, "Parameter type does not match");
1926         return nullptr;
1927     }
1928     size_t len = 0;
1929     status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len);
1930     if (status != napi_ok) {
1931         HiLog::Error(LABEL, "Get field length failed");
1932         return nullptr;
1933     }
1934     std::vector<char> buf(len + 1);
1935     status = napi_get_value_string_utf8(env, argv[0], buf.data(), len + 1, &len);
1936     if (status != napi_ok) {
1937         HiLog::Error(LABEL, "Get string value failed");
1938         return nullptr;
1939     }
1940     obj->brkiter_->setText(buf.data());
1941     return nullptr;
1942 }
1943 
GetText(napi_env env,napi_callback_info info)1944 napi_value I18nAddon::GetText(napi_env env, napi_callback_info info)
1945 {
1946     size_t argc = 0;
1947     napi_value *argv = nullptr;
1948     napi_value thisVar = nullptr;
1949     void *data = nullptr;
1950     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1951     I18nAddon *obj = nullptr;
1952     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
1953     if (status != napi_ok || !obj || !obj->brkiter_) {
1954         HiLog::Error(LABEL, "Get BreakIterator object failed");
1955         return nullptr;
1956     }
1957     napi_value value = nullptr;
1958     std::string temp;
1959     obj->brkiter_->getText(temp);
1960     status = napi_create_string_utf8(env, temp.c_str(), NAPI_AUTO_LENGTH, &value);
1961     if (status != napi_ok) {
1962         HiLog::Error(LABEL, "Get field length failed");
1963         return nullptr;
1964     }
1965     return value;
1966 }
1967 
Following(napi_env env,napi_callback_info info)1968 napi_value I18nAddon::Following(napi_env env, napi_callback_info info)
1969 {
1970     size_t argc = 1;
1971     napi_value argv[1] = { 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->brkiter_) {
1978         HiLog::Error(LABEL, "Get BreakIterator object failed");
1979         return nullptr;
1980     }
1981     if (!argv[0]) {
1982         return nullptr;
1983     }
1984     napi_valuetype valueType = napi_valuetype::napi_undefined;
1985     napi_typeof(env, argv[0], &valueType);
1986     if (valueType != napi_valuetype::napi_number) {
1987         napi_throw_type_error(env, nullptr, "Parameter type does not match");
1988         return nullptr;
1989     }
1990     int value;
1991     status = napi_get_value_int32(env, argv[0], &value);
1992     if (status != napi_ok) {
1993         HiLog::Error(LABEL, "Retrieve following value failed");
1994         return nullptr;
1995     }
1996     value = obj->brkiter_->following(value);
1997     napi_value result = nullptr;
1998     status = napi_create_int32(env, value, &result);
1999     if (status != napi_ok) {
2000         HiLog::Error(LABEL, "Create int32_t value failed");
2001         return nullptr;
2002     }
2003     return result;
2004 }
2005 
IsBoundary(napi_env env,napi_callback_info info)2006 napi_value I18nAddon::IsBoundary(napi_env env, napi_callback_info info)
2007 {
2008     size_t argc = 1;
2009     napi_value argv[1] = { nullptr };
2010     napi_value thisVar = nullptr;
2011     void *data = nullptr;
2012     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2013     I18nAddon *obj = nullptr;
2014     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
2015     if (status != napi_ok || !obj || !obj->brkiter_) {
2016         HiLog::Error(LABEL, "Get BreakIterator object failed");
2017         return nullptr;
2018     }
2019     if (!argv[0]) {
2020         return nullptr;
2021     }
2022     napi_valuetype valueType = napi_valuetype::napi_undefined;
2023     int value;
2024     napi_typeof(env, argv[0], &valueType);
2025     if (valueType != napi_valuetype::napi_number) {
2026         napi_throw_type_error(env, nullptr, "Parameter type does not match");
2027         return nullptr;
2028     }
2029     status = napi_get_value_int32(env, argv[0], &value);
2030     if (status != napi_ok) {
2031         HiLog::Error(LABEL, "Retrieve following value failed");
2032         return nullptr;
2033     }
2034     bool boundary = obj->brkiter_->isBoundary(value);
2035     napi_value result = nullptr;
2036     status = napi_get_boolean(env, boundary, &result);
2037     if (status != napi_ok) {
2038         HiLog::Error(LABEL, "Create boolean failed");
2039         return nullptr;
2040     }
2041     return result;
2042 }
2043 
IndexUtilConstructor(napi_env env,napi_callback_info info)2044 napi_value I18nAddon::IndexUtilConstructor(napi_env env, napi_callback_info info)
2045 {
2046     size_t argc = 1;
2047     napi_value argv[1] = { 0 };
2048     napi_value thisVar = nullptr;
2049     void *data = nullptr;
2050     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2051     std::string localeTag = "";
2052     if (argv[0] != nullptr) {
2053         napi_valuetype valueType = napi_valuetype::napi_undefined;
2054         napi_typeof(env, argv[0], &valueType);
2055         if (valueType != napi_valuetype::napi_string) {
2056             napi_throw_type_error(env, nullptr, "Parameter type does not match");
2057             return nullptr;
2058         }
2059         size_t len = 0;
2060         status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len);
2061         if (status != napi_ok) {
2062             HiLog::Error(LABEL, "Get locale length failed");
2063             return nullptr;
2064         }
2065         std::vector<char> localeBuf(len + 1);
2066         status = napi_get_value_string_utf8(env, argv[0], localeBuf.data(), len + 1, &len);
2067         if (status != napi_ok) {
2068             HiLog::Error(LABEL, "Get locale failed");
2069             return nullptr;
2070         }
2071         localeTag = localeBuf.data();
2072     }
2073     std::unique_ptr<I18nAddon> obj = nullptr;
2074     obj = std::make_unique<I18nAddon>();
2075     if (!obj) {
2076         HiLog::Error(LABEL, "Create I18nAddon failed");
2077         return nullptr;
2078     }
2079     status =
2080         napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()), I18nAddon::Destructor, nullptr, &obj->wrapper_);
2081     if (status != napi_ok) {
2082         HiLog::Error(LABEL, "Wrap II18nAddon failed");
2083         return nullptr;
2084     }
2085     if (!obj->InitIndexUtilContext(env, info, localeTag)) {
2086         return nullptr;
2087     }
2088     obj.release();
2089     return thisVar;
2090 }
2091 
InitIndexUtilContext(napi_env env,napi_callback_info info,const std::string & localeTag)2092 bool I18nAddon::InitIndexUtilContext(napi_env env, napi_callback_info info, const std::string &localeTag)
2093 {
2094     napi_value global = nullptr;
2095     napi_status status = napi_get_global(env, &global);
2096     if (status != napi_ok) {
2097         HiLog::Error(LABEL, "Get global failed");
2098         return false;
2099     }
2100     env_ = env;
2101     indexUtil_ = std::make_unique<IndexUtil>(localeTag);
2102     return indexUtil_ != nullptr;
2103 }
2104 
GetIndexUtil(napi_env env,napi_callback_info info)2105 napi_value I18nAddon::GetIndexUtil(napi_env env, napi_callback_info info)
2106 {
2107     size_t argc = 1;
2108     napi_value argv[1] = { 0 };
2109     napi_value thisVar = nullptr;
2110     void *data = nullptr;
2111     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2112     napi_value constructor = nullptr;
2113     napi_status status = napi_get_reference_value(env, g_indexUtilConstructor, &constructor);
2114     if (status != napi_ok) {
2115         HiLog::Error(LABEL, "Failed to create reference at GetIndexUtil");
2116         return nullptr;
2117     }
2118     napi_value result = nullptr;
2119     if (!argv[0]) {
2120         status = napi_new_instance(env, constructor, 0, argv, &result);
2121     } else {
2122         status = napi_new_instance(env, constructor, 1, argv, &result);
2123     }
2124     if (status != napi_ok) {
2125         HiLog::Error(LABEL, "Get calendar create instance failed");
2126         return nullptr;
2127     }
2128     return result;
2129 }
2130 
GetIndexList(napi_env env,napi_callback_info info)2131 napi_value I18nAddon::GetIndexList(napi_env env, napi_callback_info info)
2132 {
2133     size_t argc = 0;
2134     napi_value argv[0];
2135     napi_value thisVar = nullptr;
2136     void *data = nullptr;
2137     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2138 
2139     I18nAddon *obj = nullptr;
2140     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
2141     if (status != napi_ok || !obj || !obj->indexUtil_) {
2142         HiLog::Error(LABEL, "GetPhoneNumberFormat object failed");
2143         return nullptr;
2144     }
2145 
2146     std::vector<std::string> indexList = obj->indexUtil_->GetIndexList();
2147     napi_value result = nullptr;
2148     status = napi_create_array_with_length(env, indexList.size(), &result);
2149     if (status != napi_ok) {
2150         HiLog::Error(LABEL, "Failed to create array");
2151         return nullptr;
2152     }
2153     for (size_t i = 0; i < indexList.size(); i++) {
2154         napi_value element = nullptr;
2155         status = napi_create_string_utf8(env, indexList[i].c_str(), NAPI_AUTO_LENGTH, &element);
2156         if (status != napi_ok) {
2157             HiLog::Error(LABEL, "Failed to create string item");
2158             return nullptr;
2159         }
2160         status = napi_set_element(env, result, i, element);
2161         if (status != napi_ok) {
2162             HiLog::Error(LABEL, "Failed to set array item");
2163             return nullptr;
2164         }
2165     }
2166     return result;
2167 }
2168 
AddLocale(napi_env env,napi_callback_info info)2169 napi_value I18nAddon::AddLocale(napi_env env, napi_callback_info info)
2170 {
2171     size_t argc = 1;
2172     napi_value argv[1] = { 0 };
2173     napi_value thisVar = nullptr;
2174     void *data = nullptr;
2175     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2176     napi_valuetype valueType = napi_valuetype::napi_undefined;
2177     napi_typeof(env, argv[0], &valueType);
2178     if (valueType != napi_valuetype::napi_string) {
2179         napi_throw_type_error(env, nullptr, "Parameter type does not match");
2180         return nullptr;
2181     }
2182     size_t len = 0;
2183     napi_status status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len);
2184     if (status != napi_ok) {
2185         HiLog::Error(LABEL, "Get locale length failed");
2186         return nullptr;
2187     }
2188     std::vector<char> buf(len + 1);
2189     status = napi_get_value_string_utf8(env, argv[0], buf.data(), len + 1, &len);
2190     if (status != napi_ok) {
2191         HiLog::Error(LABEL, "Get locale failed");
2192         return nullptr;
2193     }
2194     I18nAddon *obj = nullptr;
2195     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
2196     if (status != napi_ok || !obj || !obj->indexUtil_) {
2197         HiLog::Error(LABEL, "Get IndexUtil object failed");
2198         return nullptr;
2199     }
2200     obj->indexUtil_->AddLocale(buf.data());
2201     return nullptr;
2202 }
2203 
GetIndex(napi_env env,napi_callback_info info)2204 napi_value I18nAddon::GetIndex(napi_env env, napi_callback_info info)
2205 {
2206     size_t argc = 1;
2207     napi_value argv[1] = { 0 };
2208     napi_value thisVar = nullptr;
2209     void *data = nullptr;
2210     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2211     napi_valuetype valueType = napi_valuetype::napi_undefined;
2212     napi_typeof(env, argv[0], &valueType);
2213     if (valueType != napi_valuetype::napi_string) {
2214         napi_throw_type_error(env, nullptr, "Parameter type does not match");
2215         return nullptr;
2216     }
2217     size_t len = 0;
2218     napi_status status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len);
2219     if (status != napi_ok) {
2220         HiLog::Error(LABEL, "Get String length failed");
2221         return nullptr;
2222     }
2223     std::vector<char> buf(len + 1);
2224     status = napi_get_value_string_utf8(env, argv[0], buf.data(), len + 1, &len);
2225     if (status != napi_ok) {
2226         HiLog::Error(LABEL, "Get String failed");
2227         return nullptr;
2228     }
2229     I18nAddon *obj = nullptr;
2230     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
2231     if (status != napi_ok || !obj || !obj->indexUtil_) {
2232         HiLog::Error(LABEL, "Get IndexUtil object failed");
2233         return nullptr;
2234     }
2235     std::string index = obj->indexUtil_->GetIndex(buf.data());
2236     napi_value result = nullptr;
2237     status = napi_create_string_utf8(env, index.c_str(), NAPI_AUTO_LENGTH, &result);
2238     if (status != napi_ok) {
2239         HiLog::Error(LABEL, "GetIndex Failed");
2240         return nullptr;
2241     }
2242     return result;
2243 }
2244 
Is24HourClock(napi_env env,napi_callback_info info)2245 napi_value I18nAddon::Is24HourClock(napi_env env, napi_callback_info info)
2246 {
2247     bool is24HourClock = LocaleConfig::Is24HourClock();
2248     napi_value result = nullptr;
2249     napi_status status = napi_get_boolean(env, is24HourClock, &result);
2250     if (status != napi_ok) {
2251         HiLog::Error(LABEL, "Failed to create boolean item");
2252         return nullptr;
2253     }
2254     return result;
2255 }
2256 
Set24HourClock(napi_env env,napi_callback_info info)2257 napi_value I18nAddon::Set24HourClock(napi_env env, napi_callback_info info)
2258 {
2259     size_t argc = 1;
2260     napi_value argv[1] = { 0 };
2261     napi_value thisVar = nullptr;
2262     void *data = nullptr;
2263     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2264 
2265     bool option = false;
2266     status = napi_get_value_bool(env, argv[0], &option);
2267     if (status != napi_ok) {
2268         HiLog::Error(LABEL, "Failed to get boolean item");
2269         return nullptr;
2270     }
2271     bool success = LocaleConfig::Set24HourClock(option);
2272     napi_value result = nullptr;
2273     status = napi_get_boolean(env, success, &result);
2274     if (status != napi_ok) {
2275         HiLog::Error(LABEL, "Create set 24HourClock boolean value failed");
2276         return nullptr;
2277     }
2278     return result;
2279 }
2280 
AddPreferredLanguage(napi_env env,napi_callback_info info)2281 napi_value I18nAddon::AddPreferredLanguage(napi_env env, napi_callback_info info)
2282 {
2283     size_t argc = 2;
2284     napi_value argv[2] = { 0 };
2285     napi_value thisVar = nullptr;
2286     void *data = nullptr;
2287     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2288 
2289     napi_valuetype valueType = napi_valuetype::napi_undefined;
2290     napi_typeof(env, argv[0], &valueType);
2291     if (valueType != napi_valuetype::napi_string) {
2292         napi_throw_type_error(env, nullptr, "addPreferredLanguage: first parameter type does not match");
2293         return nullptr;
2294     }
2295     size_t len = 0;
2296     status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len);
2297     if (status != napi_ok) {
2298         HiLog::Error(LABEL, "addPreferredLanguage: get language length failed");
2299         return nullptr;
2300     }
2301     std::vector<char> language(len + 1);
2302     status = napi_get_value_string_utf8(env, argv[0], language.data(), len + 1, &len);
2303     if (status != napi_ok) {
2304         HiLog::Error(LABEL, "addPreferrdLanguage: get language failed");
2305         return nullptr;
2306     }
2307     int index = 1000000;
2308     if (argv[1] != nullptr) {
2309         status = napi_get_value_int32(env, argv[1], &index);
2310     }
2311     if (status != napi_ok) {
2312         HiLog::Error(LABEL, "addPreferrdLanguage: get index failed");
2313         return nullptr;
2314     }
2315     bool success = PreferredLanguage::AddPreferredLanguage(language.data(), index);
2316     napi_value result = nullptr;
2317     status = napi_get_boolean(env, success, &result);
2318     if (status != napi_ok) {
2319         HiLog::Error(LABEL, "addPreferrdLanguage: create boolean result failed");
2320         return nullptr;
2321     }
2322     return result;
2323 }
2324 
RemovePreferredLanguage(napi_env env,napi_callback_info info)2325 napi_value I18nAddon::RemovePreferredLanguage(napi_env env, napi_callback_info info)
2326 {
2327     size_t argc = 1;
2328     napi_value argv[1] = { 0 };
2329     napi_value thisVar = nullptr;
2330     void *data = nullptr;
2331     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2332 
2333     napi_valuetype valueType = napi_valuetype::napi_undefined;
2334     napi_typeof(env, argv[0], &valueType);
2335     if (valueType != napi_valuetype::napi_number) {
2336         napi_throw_type_error(env, nullptr, "removePreferredLanguage: parameter type does not match");
2337         return nullptr;
2338     }
2339     int index = 1000000;
2340     status = napi_get_value_int32(env, argv[0], &index);
2341     if (status != napi_ok) {
2342         HiLog::Error(LABEL, "removePreferrdLanguage: get index failed");
2343         return nullptr;
2344     }
2345     bool success = PreferredLanguage::RemovePreferredLanguage(index);
2346     napi_value result = nullptr;
2347     status = napi_get_boolean(env, success, &result);
2348     if (status != napi_ok) {
2349         HiLog::Error(LABEL, "removePreferrdLanguage: create boolean result failed");
2350         return nullptr;
2351     }
2352     return result;
2353 }
2354 
GetPreferredLanguageList(napi_env env,napi_callback_info info)2355 napi_value I18nAddon::GetPreferredLanguageList(napi_env env, napi_callback_info info)
2356 {
2357     std::vector<std::string> languageList = PreferredLanguage::GetPreferredLanguageList();
2358     napi_value result = nullptr;
2359     napi_status status = napi_ok;
2360     status = napi_create_array_with_length(env, languageList.size(), &result);
2361     if (status != napi_ok) {
2362         HiLog::Error(LABEL, "getPreferrdLanguageList: create array failed");
2363         return nullptr;
2364     }
2365     for (size_t i = 0; i < languageList.size(); i++) {
2366         napi_value value = nullptr;
2367         status = napi_create_string_utf8(env, languageList[i].c_str(), NAPI_AUTO_LENGTH, &value);
2368         if (status != napi_ok) {
2369             HiLog::Error(LABEL, "getPreferrdLanguageList: create string failed");
2370             return nullptr;
2371         }
2372         status = napi_set_element(env, result, i, value);
2373         if (status != napi_ok) {
2374             HiLog::Error(LABEL, "GetPreferredLanguageList: set array item failed");
2375             return nullptr;
2376         }
2377     }
2378     return result;
2379 }
2380 
GetFirstPreferredLanguage(napi_env env,napi_callback_info info)2381 napi_value I18nAddon::GetFirstPreferredLanguage(napi_env env, napi_callback_info info)
2382 {
2383     std::string language = PreferredLanguage::GetFirstPreferredLanguage();
2384     napi_value result = nullptr;
2385     napi_status status = napi_ok;
2386     status = napi_create_string_utf8(env, language.c_str(), NAPI_AUTO_LENGTH, &result);
2387     if (status != napi_ok) {
2388         HiLog::Error(LABEL, "getFirstPreferrdLanguage: create string result failed");
2389         return nullptr;
2390     }
2391     return result;
2392 }
2393 
InitI18nTimeZone(napi_env env,napi_value exports)2394 napi_value I18nAddon::InitI18nTimeZone(napi_env env, napi_value exports)
2395 {
2396     napi_status status = napi_ok;
2397     napi_property_descriptor properties[] = {
2398         DECLARE_NAPI_FUNCTION("getID", GetID),
2399         DECLARE_NAPI_FUNCTION("getDisplayName", GetTimeZoneDisplayName),
2400         DECLARE_NAPI_FUNCTION("getRawOffset", GetRawOffset),
2401         DECLARE_NAPI_FUNCTION("getOffset", GetOffset),
2402     };
2403     napi_value constructor = nullptr;
2404     status = napi_define_class(env, "TimeZone", NAPI_AUTO_LENGTH, I18nTimeZoneConstructor, nullptr,
2405         sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor);
2406     if (status != napi_ok) {
2407         HiLog::Error(LABEL, "Failed to define class TimeZone at Init");
2408         return nullptr;
2409     }
2410     g_timezoneConstructor = new (std::nothrow) napi_ref;
2411     if (!g_timezoneConstructor) {
2412         HiLog::Error(LABEL, "Failed to create TimeZone ref at init");
2413         return nullptr;
2414     }
2415     status = napi_create_reference(env, constructor, 1, g_timezoneConstructor);
2416     if (status != napi_ok) {
2417         HiLog::Error(LABEL, "Failed to create reference g_timezoneConstructor at init");
2418         return nullptr;
2419     }
2420     return exports;
2421 }
2422 
I18nTimeZoneConstructor(napi_env env,napi_callback_info info)2423 napi_value I18nAddon::I18nTimeZoneConstructor(napi_env env, napi_callback_info info)
2424 {
2425     size_t argc = 1;
2426     napi_value argv[1] = { nullptr };
2427     napi_value thisVar = nullptr;
2428     void *data = nullptr;
2429     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2430     if (status != napi_ok) {
2431         return nullptr;
2432     }
2433     std::string zoneID = "";
2434     if (argv[0] != nullptr) {
2435         napi_valuetype valueType = napi_valuetype::napi_undefined;
2436         napi_typeof(env, argv[0], &valueType);
2437         if (valueType != napi_valuetype::napi_string) {
2438             napi_throw_type_error(env, nullptr, "Parameter type does not match");
2439             return nullptr;
2440         }
2441         int32_t code = 0;
2442         zoneID = GetString(env, argv[0], code);
2443         if (code != 0) {
2444             return nullptr;
2445         }
2446     }
2447     std::unique_ptr<I18nAddon> obj = nullptr;
2448     obj = std::make_unique<I18nAddon>();
2449     if (!obj) {
2450         HiLog::Error(LABEL, "Create I18nAddon failed");
2451         return nullptr;
2452     }
2453     status =
2454         napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()), I18nAddon::Destructor, nullptr, &obj->wrapper_);
2455     if (status != napi_ok) {
2456         HiLog::Error(LABEL, "Wrap II18nAddon failed");
2457         return nullptr;
2458     }
2459     obj->timezone_ = std::make_unique<I18nTimeZone>(zoneID);
2460     if (!obj->timezone_) {
2461         HiLog::Error(LABEL, "Wrap TimeZone failed");
2462         return nullptr;
2463     }
2464     obj.release();
2465     return thisVar;
2466 }
2467 
GetI18nTimeZone(napi_env env,napi_callback_info info)2468 napi_value I18nAddon::GetI18nTimeZone(napi_env env, napi_callback_info info)
2469 {
2470     size_t argc = 1;
2471     napi_value argv[1] = { nullptr };
2472     napi_value thisVar = nullptr;
2473     void *data = nullptr;
2474     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2475     napi_value constructor = nullptr;
2476     napi_status status = napi_get_reference_value(env, *g_timezoneConstructor, &constructor);
2477     if (status != napi_ok) {
2478         HiLog::Error(LABEL, "Failed to create reference at GetTimeZoneInstance");
2479         return nullptr;
2480     }
2481 
2482     napi_value result = nullptr;
2483     if (!argv[0]) {
2484         status = napi_new_instance(env, constructor, 0, nullptr, &result); // 1 arguments
2485     } else {
2486         status = napi_new_instance(env, constructor, 1, argv, &result); // 1 arguments
2487     }
2488     if (status != napi_ok) {
2489         HiLog::Error(LABEL, "GetTimeZone create instance failed");
2490         return nullptr;
2491     }
2492     return result;
2493 }
2494 
GetID(napi_env env,napi_callback_info info)2495 napi_value I18nAddon::GetID(napi_env env, napi_callback_info info)
2496 {
2497     size_t argc = 0;
2498     napi_value *argv = nullptr;
2499     napi_value thisVar = nullptr;
2500     void *data = nullptr;
2501     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2502     I18nAddon *obj = nullptr;
2503     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
2504     if (status != napi_ok || !obj || !obj->timezone_) {
2505         HiLog::Error(LABEL, "Get TimeZone object failed");
2506         return nullptr;
2507     }
2508     std::string result = obj->timezone_->GetID();
2509     napi_value value = nullptr;
2510     status = napi_create_string_utf8(env, result.c_str(), NAPI_AUTO_LENGTH, &value);
2511     if (status != napi_ok) {
2512         HiLog::Error(LABEL, "Create result failed");
2513         return nullptr;
2514     }
2515     return value;
2516 }
2517 
GetStringFromJS(napi_env env,napi_value argv,std::string & jsString)2518 bool I18nAddon::GetStringFromJS(napi_env env, napi_value argv, std::string &jsString)
2519 {
2520     size_t len = 0;
2521     napi_status status = napi_get_value_string_utf8(env, argv, nullptr, 0, &len);
2522     if (status != napi_ok) {
2523         HiLog::Error(LABEL, "Failed to get string length");
2524         return false;
2525     }
2526     std::vector<char> argvBuf(len + 1);
2527     status = napi_get_value_string_utf8(env, argv, argvBuf.data(), len + 1, &len);
2528     if (status != napi_ok) {
2529         HiLog::Error(LABEL, "Failed to get string item");
2530         return false;
2531     }
2532     jsString = argvBuf.data();
2533     return true;
2534 }
2535 
GetParameter(napi_env env,napi_value * argv,std::string & localeStr,bool & isDST)2536 int32_t I18nAddon::GetParameter(napi_env env, napi_value *argv, std::string &localeStr, bool &isDST)
2537 {
2538     if (!argv[0]) {
2539         return 0;  // 0 represents no parameter.
2540     }
2541     napi_status status = napi_ok;
2542     if (!argv[1]) {
2543         napi_valuetype valueType = napi_valuetype::napi_undefined;
2544         napi_typeof(env, argv[0], &valueType);
2545         if (valueType == napi_valuetype::napi_string) {
2546             bool valid = GetStringFromJS(env, argv[0], localeStr);
2547             if (!valid) {
2548                 return -1;  // -1 represents Invalid parameter.
2549             }
2550             return 1;  // 1 represents one string parameter.
2551         } else if (valueType == napi_valuetype::napi_boolean) {
2552             status = napi_get_value_bool(env, argv[0], &isDST);
2553             if (status != napi_ok) {
2554                 return -1;  // -1 represents Invalid parameter.
2555             }
2556             return 2;  // 2 represents one boolean parameter.
2557         } else {
2558             return -1;  // -1 represents Invalid parameter.
2559         }
2560     }
2561     napi_valuetype valueType0 = napi_valuetype::napi_undefined;
2562     napi_valuetype valueType1 = napi_valuetype::napi_undefined;
2563     napi_typeof(env, argv[0], &valueType0);  // 0 represents first parameter
2564     napi_typeof(env, argv[1], &valueType1);  // 0 represents second parameter
2565     if (valueType0 != napi_valuetype::napi_string || valueType1 != napi_valuetype::napi_boolean) {
2566         return -1;  // -1 represents Invalid parameter.
2567     }
2568     bool valid = GetStringFromJS(env, argv[0], localeStr);
2569     if (!valid) {
2570         return -1;  // -1 represents Invalid parameter.
2571     }
2572     status = napi_get_value_bool(env, argv[1], &isDST);
2573     if (status != napi_ok) {
2574         return -1;  // -1 represents Invalid parameter.
2575     }
2576     return 3;  // 3 represents one string parameter and one bool parameter.
2577 }
2578 
GetTimeZoneDisplayName(napi_env env,napi_callback_info info)2579 napi_value I18nAddon::GetTimeZoneDisplayName(napi_env env, napi_callback_info info)
2580 {
2581     size_t argc = 2;
2582     napi_value argv[2] = { 0 };
2583     napi_value thisVar = nullptr;
2584     void *data = nullptr;
2585     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2586 
2587     I18nAddon *obj = nullptr;
2588     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
2589     if (status != napi_ok || !obj || !obj->timezone_) {
2590         HiLog::Error(LABEL, "Get TimeZone object failed");
2591         return nullptr;
2592     }
2593 
2594     std::string locale;
2595     bool isDST = false;
2596     int32_t parameterStatus = GetParameter(env, argv, locale, isDST);
2597 
2598     std::string result;
2599     if (parameterStatus == -1) {  // -1 represents Invalid parameter.
2600         napi_throw_type_error(env, nullptr, "Parameter type does not match");
2601         return nullptr;
2602     } else if (parameterStatus == 0) {
2603         result = obj->timezone_->GetDisplayName();
2604     } else if (parameterStatus == 1) {  // 1 represents one string parameter.
2605         result = obj->timezone_->GetDisplayName(locale);
2606     } else if (parameterStatus == 2) {  // 2 represents one boolean parameter.
2607         result = obj->timezone_->GetDisplayName(isDST);
2608     } else {
2609         result = obj->timezone_->GetDisplayName(locale, isDST);
2610     }
2611 
2612     napi_value value = nullptr;
2613     status = napi_create_string_utf8(env, result.c_str(), NAPI_AUTO_LENGTH, &value);
2614     if (status != napi_ok) {
2615         HiLog::Error(LABEL, "Create result failed");
2616         return nullptr;
2617     }
2618     return value;
2619 }
2620 
GetOffset(napi_env env,napi_callback_info info)2621 napi_value I18nAddon::GetOffset(napi_env env, napi_callback_info info)
2622 {
2623     size_t argc = 1;
2624     napi_value argv[1] = { 0 };
2625     napi_value thisVar = nullptr;
2626     void *data = nullptr;
2627     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2628 
2629     double date = 0;
2630     if (argv[0]) {
2631         napi_valuetype valueType = napi_valuetype::napi_undefined;
2632         napi_typeof(env, argv[0], &valueType);
2633         if (valueType != napi_valuetype::napi_number) {
2634             HiLog::Error(LABEL, "Invalid parameter type");
2635             return nullptr;
2636         }
2637         status = napi_get_value_double(env, argv[0], &date);
2638         if (status != napi_ok) {
2639             HiLog::Error(LABEL, "Get parameter date failed");
2640             return nullptr;
2641         }
2642     } else {
2643         auto time = std::chrono::system_clock::now();
2644         auto since_epoch = time.time_since_epoch();
2645         auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(since_epoch);
2646         date = (double)millis.count();
2647     }
2648 
2649     I18nAddon *obj = nullptr;
2650     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
2651     if (status != napi_ok || !obj || !obj->timezone_) {
2652         HiLog::Error(LABEL, "Get TimeZone object failed");
2653         return nullptr;
2654     }
2655     int32_t result = obj->timezone_->GetOffset(date);
2656     napi_value value = nullptr;
2657     status = napi_create_int32(env, result, &value);
2658     if (status != napi_ok) {
2659         HiLog::Error(LABEL, "Create result failed");
2660         return nullptr;
2661     }
2662     return value;
2663 }
2664 
GetRawOffset(napi_env env,napi_callback_info info)2665 napi_value I18nAddon::GetRawOffset(napi_env env, napi_callback_info info)
2666 {
2667     size_t argc = 0;
2668     napi_value *argv = nullptr;
2669     napi_value thisVar = nullptr;
2670     void *data = nullptr;
2671     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2672     I18nAddon *obj = nullptr;
2673     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
2674     if (status != napi_ok || !obj || !obj->timezone_) {
2675         HiLog::Error(LABEL, "Get TimeZone object failed");
2676         return nullptr;
2677     }
2678     int32_t result = obj->timezone_->GetRawOffset();
2679     napi_value value = nullptr;
2680     status = napi_create_int32(env, result, &value);
2681     if (status != napi_ok) {
2682         HiLog::Error(LABEL, "Create result failed");
2683         return nullptr;
2684     }
2685     return value;
2686 }
2687 
Init(napi_env env,napi_value exports)2688 napi_value Init(napi_env env, napi_value exports)
2689 {
2690     napi_value val = I18nAddon::Init(env, exports);
2691     val = I18nAddon::InitPhoneNumberFormat(env, val);
2692     val = I18nAddon::InitBreakIterator(env, val);
2693     val = I18nAddon::InitI18nCalendar(env, val);
2694     val = I18nAddon::InitIndexUtil(env, val);
2695     return I18nAddon::InitI18nTimeZone(env, val);
2696 }
2697 
2698 static napi_module g_i18nModule = {
2699     .nm_version = 1,
2700     .nm_flags = 0,
2701     .nm_filename = nullptr,
2702     .nm_register_func = Init,
2703     .nm_modname = "i18n",
2704     .nm_priv = ((void *)0),
2705     .reserved = { 0 }
2706 };
2707 
I18nRegister()2708 extern "C" __attribute__((constructor)) void I18nRegister()
2709 {
2710     napi_module_register(&g_i18nModule);
2711 }
2712 } // namespace I18n
2713 } // namespace Global
2714 } // namespace OHOS
2715