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