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