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