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