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