1 /*
2 * Copyright (c) 2021-2025 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 "intl_addon.h"
16
17 #include <set>
18 #include <vector>
19
20 #include "node_api.h"
21
22 #include "collator_addon.h"
23 #include "displaynames_addon.h"
24 #include "error_util.h"
25 #include "i18n_hilog.h"
26 #include "intl_date_time_format_addon.h"
27 #include "intl_plural_rules_addon.h"
28 #include "js_number_format_addon.h"
29 #include "js_relative_time_format_addon.h"
30 #include "js_utils.h"
31 #include "locale_info_addon.h"
32 #include "number_format_addon.h"
33 #include "utils.h"
34
35 namespace OHOS {
36 namespace Global {
37 namespace I18n {
IntlAddon()38 IntlAddon::IntlAddon() : env_(nullptr) {}
39
~IntlAddon()40 IntlAddon::~IntlAddon()
41 {
42 }
43
Destructor(napi_env env,void * nativeObject,void * hint)44 void IntlAddon::Destructor(napi_env env, void *nativeObject, void *hint)
45 {
46 if (!nativeObject) {
47 return;
48 }
49 delete reinterpret_cast<IntlAddon *>(nativeObject);
50 nativeObject = nullptr;
51 }
52
InitDateTimeFormat(napi_env env,napi_value exports)53 napi_value IntlAddon::InitDateTimeFormat(napi_env env, napi_value exports)
54 {
55 napi_property_descriptor properties[] = {
56 DECLARE_NAPI_FUNCTION("format", FormatDateTime),
57 DECLARE_NAPI_FUNCTION("formatRange", FormatDateTimeRange),
58 DECLARE_NAPI_FUNCTION("resolvedOptions", GetDateTimeResolvedOptions)
59 };
60
61 napi_value constructor = nullptr;
62 napi_status status = status = napi_define_class(env, "DateTimeFormat", NAPI_AUTO_LENGTH, DateTimeFormatConstructor,
63 nullptr, sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor);
64 if (status != napi_ok) {
65 HILOG_ERROR_I18N("Define class failed when InitDateTimeFormat");
66 return nullptr;
67 }
68
69 status = napi_set_named_property(env, exports, "DateTimeFormat", constructor);
70 if (status != napi_ok) {
71 HILOG_ERROR_I18N("Set property failed when InitDateTimeFormat");
72 return nullptr;
73 }
74 return exports;
75 }
76
InitRelativeTimeFormat(napi_env env,napi_value exports)77 napi_value IntlAddon::InitRelativeTimeFormat(napi_env env, napi_value exports)
78 {
79 napi_property_descriptor properties[] = {
80 DECLARE_NAPI_FUNCTION("format", FormatRelativeTime),
81 DECLARE_NAPI_FUNCTION("formatToParts", FormatToParts),
82 DECLARE_NAPI_FUNCTION("resolvedOptions", GetRelativeTimeResolvedOptions)
83 };
84
85 napi_value constructor = nullptr;
86 napi_status status = status = napi_define_class(env, "RelativeTimeFormat", NAPI_AUTO_LENGTH,
87 RelativeTimeFormatConstructor, nullptr, sizeof(properties) / sizeof(napi_property_descriptor),
88 properties, &constructor);
89 if (status != napi_ok) {
90 HILOG_ERROR_I18N("Define class failed when InitRelativeTimeFormat");
91 return nullptr;
92 }
93
94 status = napi_set_named_property(env, exports, "RelativeTimeFormat", constructor);
95 if (status != napi_ok) {
96 HILOG_ERROR_I18N("Set property failed when InitRelativeTimeFormat");
97 return nullptr;
98 }
99 return exports;
100 }
101
GetDateOptionValues(napi_env env,napi_value options,std::map<std::string,std::string> & map)102 void GetDateOptionValues(napi_env env, napi_value options, std::map<std::string, std::string> &map)
103 {
104 JSUtils::GetOptionValue(env, options, "calendar", map);
105 JSUtils::GetOptionValue(env, options, "dateStyle", map);
106 JSUtils::GetOptionValue(env, options, "timeStyle", map);
107 JSUtils::GetOptionValue(env, options, "hourCycle", map);
108 JSUtils::GetOptionValue(env, options, "timeZone", map);
109 JSUtils::GetOptionValue(env, options, "timeZoneName", map);
110 JSUtils::GetOptionValue(env, options, "numberingSystem", map);
111 JSUtils::GetBoolOptionValue(env, options, "hour12", map);
112 JSUtils::GetOptionValue(env, options, "weekday", map);
113 JSUtils::GetOptionValue(env, options, "era", map);
114 JSUtils::GetOptionValue(env, options, "year", map);
115 JSUtils::GetOptionValue(env, options, "month", map);
116 JSUtils::GetOptionValue(env, options, "day", map);
117 JSUtils::GetOptionValue(env, options, "hour", map);
118 JSUtils::GetOptionValue(env, options, "minute", map);
119 JSUtils::GetOptionValue(env, options, "second", map);
120 JSUtils::GetOptionValue(env, options, "localeMatcher", map);
121 JSUtils::GetOptionValue(env, options, "formatMatcher", map);
122 JSUtils::GetOptionValue(env, options, "dayPeriod", map);
123 }
124
GetRelativeTimeOptionValues(napi_env env,napi_value options,std::map<std::string,std::string> & map)125 void GetRelativeTimeOptionValues(napi_env env, napi_value options, std::map<std::string, std::string> &map)
126 {
127 JSUtils::GetOptionValue(env, options, "localeMatcher", map);
128 JSUtils::GetOptionValue(env, options, "numeric", map);
129 JSUtils::GetOptionValue(env, options, "style", map);
130 }
131
GetLocaleTag(napi_env env,napi_value argv)132 std::string GetLocaleTag(napi_env env, napi_value argv)
133 {
134 std::string localeTag = "";
135 std::vector<char> buf;
136 if (argv != nullptr) {
137 napi_valuetype valueType = napi_valuetype::napi_undefined;
138 napi_status status = napi_typeof(env, argv, &valueType);
139 if (status != napi_ok) {
140 return "";
141 }
142 if (valueType != napi_valuetype::napi_string) {
143 HILOG_ERROR_I18N("GetLocaleTag: Parameter type does not match");
144 return "";
145 }
146 size_t len = 0;
147 status = napi_get_value_string_utf8(env, argv, nullptr, 0, &len);
148 if (status != napi_ok) {
149 HILOG_ERROR_I18N("GetLocaleTag -> string: Get locale tag length failed");
150 return "";
151 }
152 buf.resize(len + 1);
153 status = napi_get_value_string_utf8(env, argv, buf.data(), len + 1, &len);
154 if (status != napi_ok) {
155 HILOG_ERROR_I18N("GetLocaleTag: Get locale tag failed");
156 return "";
157 }
158 localeTag = buf.data();
159 } else {
160 localeTag = "";
161 }
162 return localeTag;
163 }
164
DateTimeFormatConstructor(napi_env env,napi_callback_info info)165 napi_value IntlAddon::DateTimeFormatConstructor(napi_env env, napi_callback_info info)
166 {
167 size_t argc = 2;
168 napi_value argv[2] = { nullptr };
169 napi_value thisVar = nullptr;
170 void *data = nullptr;
171 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
172 if (status != napi_ok) {
173 return nullptr;
174 }
175 std::vector<std::string> localeTags;
176 if (argc > 0) {
177 int32_t code = 0;
178 std::vector<std::string> localeArray = JSUtils::GetLocaleArray(env, argv[0], code);
179 if (code != 0) {
180 return nullptr;
181 }
182 localeTags.assign(localeArray.begin(), localeArray.end());
183 }
184 std::map<std::string, std::string> map = {};
185 if (argc > 1) {
186 GetDateOptionValues(env, argv[1], map);
187 }
188 std::unique_ptr<IntlAddon> obj = std::make_unique<IntlAddon>();
189 if (obj == nullptr) {
190 return nullptr;
191 }
192 status =
193 napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()), IntlAddon::Destructor, nullptr, nullptr);
194 if (status != napi_ok) {
195 HILOG_ERROR_I18N("DateTimeFormatConstructor: Wrap IntlAddon failed");
196 return nullptr;
197 }
198 if (!obj->InitDateTimeFormatContext(env, info, localeTags, map)) {
199 HILOG_ERROR_I18N("DateTimeFormatConstructor: Init DateTimeFormat failed");
200 return nullptr;
201 }
202 obj.release();
203 return thisVar;
204 }
205
InitDateTimeFormatContext(napi_env env,napi_callback_info info,std::vector<std::string> localeTags,std::map<std::string,std::string> & map)206 bool IntlAddon::InitDateTimeFormatContext(napi_env env, napi_callback_info info, std::vector<std::string> localeTags,
207 std::map<std::string, std::string> &map)
208 {
209 napi_value global = nullptr;
210 napi_status status = napi_get_global(env, &global);
211 if (status != napi_ok) {
212 HILOG_ERROR_I18N("InitDateTimeFormatContext: Get global failed");
213 return false;
214 }
215 env_ = env;
216 datefmt_ = DateTimeFormat::CreateInstance(localeTags, map);
217
218 return datefmt_ != nullptr;
219 }
220
RelativeTimeFormatConstructor(napi_env env,napi_callback_info info)221 napi_value IntlAddon::RelativeTimeFormatConstructor(napi_env env, napi_callback_info info)
222 {
223 size_t argc = 2;
224 napi_value argv[2] = { nullptr };
225 napi_value thisVar = nullptr;
226 void *data = nullptr;
227 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
228 if (status != napi_ok) {
229 return nullptr;
230 }
231 std::vector<std::string> localeTags;
232 if (argc > 0) {
233 int32_t code = 0;
234 std::vector<std::string> localeArray = JSUtils::GetLocaleArray(env, argv[0], code);
235 if (code != 0) {
236 return nullptr;
237 }
238 localeTags.assign(localeArray.begin(), localeArray.end());
239 }
240 std::map<std::string, std::string> map = {};
241 if (argc > 1) {
242 GetRelativeTimeOptionValues(env, argv[1], map);
243 }
244 std::unique_ptr<IntlAddon> obj = std::make_unique<IntlAddon>();
245 if (obj == nullptr) {
246 return nullptr;
247 }
248 status =
249 napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()), IntlAddon::Destructor, nullptr, nullptr);
250 if (status != napi_ok) {
251 HILOG_ERROR_I18N("RelativeTimeFormatConstructor: Wrap IntlAddon failed");
252 return nullptr;
253 }
254 if (!obj->InitRelativeTimeFormatContext(env, info, localeTags, map)) {
255 HILOG_ERROR_I18N("Init RelativeTimeFormat failed");
256 return nullptr;
257 }
258 obj.release();
259 return thisVar;
260 }
261
InitRelativeTimeFormatContext(napi_env env,napi_callback_info info,std::vector<std::string> localeTags,std::map<std::string,std::string> & map)262 bool IntlAddon::InitRelativeTimeFormatContext(napi_env env, napi_callback_info info,
263 std::vector<std::string> localeTags, std::map<std::string, std::string> &map)
264 {
265 env_ = env;
266 relativetimefmt_ = std::make_unique<RelativeTimeFormat>(localeTags, map);
267
268 return relativetimefmt_ != nullptr;
269 }
270
FormatDateTime(napi_env env,napi_callback_info info)271 napi_value IntlAddon::FormatDateTime(napi_env env, napi_callback_info info)
272 {
273 size_t argc = 1;
274 napi_value argv[1] = { 0 };
275 napi_value thisVar = nullptr;
276 void *data = nullptr;
277 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
278 if (status != napi_ok) {
279 return nullptr;
280 }
281 int64_t milliseconds = GetMilliseconds(env, argv, 0);
282 if (milliseconds == -1) {
283 return nullptr;
284 }
285 IntlAddon *obj = nullptr;
286 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
287 if (status != napi_ok || !obj || !obj->datefmt_) {
288 HILOG_ERROR_I18N("FormatDateTime: Get DateTimeFormat object failed");
289 return nullptr;
290 }
291 std::string value = obj->datefmt_->Format(milliseconds);
292 napi_value result = nullptr;
293 status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result);
294 if (status != napi_ok) {
295 HILOG_ERROR_I18N("FormatDateTime: Create format string failed");
296 return nullptr;
297 }
298 return result;
299 }
300
FormatDateTimeRange(napi_env env,napi_callback_info info)301 napi_value IntlAddon::FormatDateTimeRange(napi_env env, napi_callback_info info)
302 {
303 size_t argc = 2;
304 napi_value argv[2] = { nullptr };
305 napi_value thisVar = nullptr;
306 void *data = nullptr;
307 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
308 if (status != napi_ok) {
309 return nullptr;
310 }
311 if (argc < FUNC_ARGS_COUNT) {
312 HILOG_ERROR_I18N("Parameter wrong");
313 return nullptr;
314 }
315 int64_t firstMilliseconds = GetMilliseconds(env, argv, 0);
316 int64_t secondMilliseconds = GetMilliseconds(env, argv, 1);
317 if (firstMilliseconds == -1 || secondMilliseconds == -1) {
318 return nullptr;
319 }
320 IntlAddon *obj = nullptr;
321 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
322 if (status != napi_ok || !obj || !obj->datefmt_) {
323 HILOG_ERROR_I18N("FormatDateTimeRange: Get DateTimeFormat object failed");
324 return nullptr;
325 }
326 std::string value = obj->datefmt_->FormatRange(firstMilliseconds, secondMilliseconds);
327 napi_value result = nullptr;
328 status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result);
329 if (status != napi_ok) {
330 HILOG_ERROR_I18N("FormatDateTimeRange: Create format string failed");
331 return nullptr;
332 }
333 return result;
334 }
335
GetMilliseconds(napi_env env,napi_value * argv,int index)336 int64_t IntlAddon::GetMilliseconds(napi_env env, napi_value *argv, int index)
337 {
338 napi_value funcGetDateInfo = nullptr;
339 napi_status status = napi_get_named_property(env, argv[index], "getTime", &funcGetDateInfo);
340 if (status != napi_ok) {
341 HILOG_ERROR_I18N("Get Milliseconds property failed");
342 return -1;
343 }
344 napi_value ret_value = nullptr;
345 status = napi_call_function(env, argv[index], funcGetDateInfo, 0, nullptr, &ret_value);
346 if (status != napi_ok) {
347 HILOG_ERROR_I18N("Get Milliseconds function failed");
348 return -1;
349 }
350 int64_t milliseconds = 0;
351 status = napi_get_value_int64(env, ret_value, &milliseconds);
352 if (status != napi_ok) {
353 HILOG_ERROR_I18N("Get Milliseconds failed");
354 return -1;
355 }
356 return milliseconds;
357 }
358
GetRelativeTimeResolvedOptions(napi_env env,napi_callback_info info)359 napi_value IntlAddon::GetRelativeTimeResolvedOptions(napi_env env, napi_callback_info info)
360 {
361 napi_value thisVar = nullptr;
362 void *data = nullptr;
363 napi_status status = napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data);
364 if (status != napi_ok) {
365 return nullptr;
366 }
367 IntlAddon *obj = nullptr;
368 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
369 if (status != napi_ok || !obj || !obj->relativetimefmt_) {
370 HILOG_ERROR_I18N("GetRelativeTimeResolvedOptions: Get RelativeTimeFormat object failed");
371 return nullptr;
372 }
373 napi_value result = nullptr;
374 status = napi_create_object(env, &result);
375 if (status != napi_ok) {
376 return nullptr;
377 }
378 std::map<std::string, std::string> options = {};
379 obj->relativetimefmt_->GetResolvedOptions(options);
380 JSUtils::SetOptionProperties(env, result, options, "locale");
381 JSUtils::SetOptionProperties(env, result, options, "style");
382 JSUtils::SetOptionProperties(env, result, options, "numeric");
383 JSUtils::SetOptionProperties(env, result, options, "numberingSystem");
384 return result;
385 }
386
GetDateTimeResolvedOptions(napi_env env,napi_callback_info info)387 napi_value IntlAddon::GetDateTimeResolvedOptions(napi_env env, napi_callback_info info)
388 {
389 napi_value thisVar = nullptr;
390 void *data = nullptr;
391 napi_status status = napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data);
392 if (status != napi_ok) {
393 return nullptr;
394 }
395 IntlAddon *obj = nullptr;
396 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
397 if (status != napi_ok || !obj || !obj->datefmt_) {
398 HILOG_ERROR_I18N("GetDateTimeResolvedOptions: Get DateTimeFormat object failed");
399 return nullptr;
400 }
401 napi_value result = nullptr;
402 status = napi_create_object(env, &result);
403 if (status != napi_ok) {
404 return nullptr;
405 }
406 std::map<std::string, std::string> options = {};
407 obj->datefmt_->GetResolvedOptions(options);
408 JSUtils::SetOptionProperties(env, result, options, "locale");
409 JSUtils::SetOptionProperties(env, result, options, "calendar");
410 JSUtils::SetOptionProperties(env, result, options, "dateStyle");
411 JSUtils::SetOptionProperties(env, result, options, "timeStyle");
412 JSUtils::SetOptionProperties(env, result, options, "hourCycle");
413 JSUtils::SetOptionProperties(env, result, options, "timeZone");
414 JSUtils::SetOptionProperties(env, result, options, "timeZoneName");
415 JSUtils::SetOptionProperties(env, result, options, "numberingSystem");
416 JSUtils::SetBooleanOptionProperties(env, result, options, "hour12");
417 JSUtils::SetOptionProperties(env, result, options, "weekday");
418 JSUtils::SetOptionProperties(env, result, options, "era");
419 JSUtils::SetOptionProperties(env, result, options, "year");
420 JSUtils::SetOptionProperties(env, result, options, "month");
421 JSUtils::SetOptionProperties(env, result, options, "day");
422 JSUtils::SetOptionProperties(env, result, options, "hour");
423 JSUtils::SetOptionProperties(env, result, options, "minute");
424 JSUtils::SetOptionProperties(env, result, options, "second");
425 JSUtils::SetOptionProperties(env, result, options, "dayPeriod");
426 JSUtils::SetOptionProperties(env, result, options, "localeMatcher");
427 JSUtils::SetOptionProperties(env, result, options, "formatMatcher");
428 return result;
429 }
430
GetCollatorLocaleMatcher(napi_env env,napi_value options,std::map<std::string,std::string> & map)431 void GetCollatorLocaleMatcher(napi_env env, napi_value options, std::map<std::string, std::string> &map)
432 {
433 JSUtils::GetOptionValue(env, options, "localeMatcher", map);
434 auto it = map.find("localeMatcher");
435 if (it != map.end()) {
436 std::string localeMatcher = it->second;
437 if (localeMatcher != "lookup" && localeMatcher != "best fit") {
438 HILOG_ERROR_I18N("invalid localeMatcher");
439 return;
440 }
441 } else {
442 map.insert(std::make_pair("localeMatcher", "best fit"));
443 }
444 }
445
GetCollatorUsage(napi_env env,napi_value options,std::map<std::string,std::string> & map)446 void GetCollatorUsage(napi_env env, napi_value options, std::map<std::string, std::string> &map)
447 {
448 JSUtils::GetOptionValue(env, options, "usage", map);
449 auto it = map.find("usage");
450 if (it != map.end()) {
451 std::string usage = it->second;
452 if (usage != "sort" && usage != "search") {
453 HILOG_ERROR_I18N("invalid usage");
454 return;
455 }
456 } else {
457 map.insert(std::make_pair("usage", "sort"));
458 }
459 }
460
GetCollatorSensitivity(napi_env env,napi_value options,std::map<std::string,std::string> & map)461 void GetCollatorSensitivity(napi_env env, napi_value options, std::map<std::string, std::string> &map)
462 {
463 JSUtils::GetOptionValue(env, options, "sensitivity", map);
464 auto it = map.find("sensitivity");
465 if (it != map.end()) {
466 std::string sensitivity = it->second;
467 if (sensitivity != "base" && sensitivity != "accent" && sensitivity != "case" && sensitivity != "variant") {
468 HILOG_ERROR_I18N("invalid sensitivity");
469 return;
470 }
471 } else {
472 map.insert(std::make_pair("sensitivity", "variant"));
473 }
474 }
475
GetCollatorIgnorePunctuation(napi_env env,napi_value options,std::map<std::string,std::string> & map)476 void GetCollatorIgnorePunctuation(napi_env env, napi_value options, std::map<std::string, std::string> &map)
477 {
478 JSUtils::GetBoolOptionValue(env, options, "ignorePunctuation", map);
479 auto it = map.find("ignorePunctuation");
480 if (it != map.end()) {
481 std::string ignorePunctuation = it->second;
482 if (ignorePunctuation != "true" && ignorePunctuation != "false") {
483 HILOG_ERROR_I18N("invalid ignorePunctuation");
484 return;
485 }
486 } else {
487 map.insert(std::make_pair("ignorePunctuation", "false"));
488 }
489 }
490
GetCollatorNumeric(napi_env env,napi_value options,std::map<std::string,std::string> & map)491 void GetCollatorNumeric(napi_env env, napi_value options, std::map<std::string, std::string> &map)
492 {
493 JSUtils::GetBoolOptionValue(env, options, "numeric", map);
494 auto it = map.find("numeric");
495 if (it != map.end()) {
496 std::string numeric = it->second;
497 if (numeric != "true" && numeric != "false") {
498 HILOG_ERROR_I18N("invalid numeric");
499 return;
500 }
501 }
502 }
503
GetCollatorCaseFirst(napi_env env,napi_value options,std::map<std::string,std::string> & map)504 void GetCollatorCaseFirst(napi_env env, napi_value options, std::map<std::string, std::string> &map)
505 {
506 JSUtils::GetOptionValue(env, options, "caseFirst", map);
507 auto it = map.find("caseFirst");
508 if (it != map.end()) {
509 std::string caseFirst = it->second;
510 if (caseFirst != "upper" && caseFirst != "lower" && caseFirst != "false") {
511 HILOG_ERROR_I18N("invalid caseFirst");
512 return;
513 }
514 }
515 }
516
GetCollatorCollation(napi_env env,napi_value options,std::map<std::string,std::string> & map)517 void GetCollatorCollation(napi_env env, napi_value options, std::map<std::string, std::string> &map)
518 {
519 JSUtils::GetOptionValue(env, options, "collation", map);
520 auto it = map.find("collation");
521 if (it != map.end()) {
522 std::string collation = it->second;
523 std::set<std::string> validCollation;
524 validCollation.insert("big5han");
525 validCollation.insert("compat");
526 validCollation.insert("dict");
527 validCollation.insert("direct");
528 validCollation.insert("ducet");
529 validCollation.insert("eor");
530 validCollation.insert("gb2312");
531 validCollation.insert("phonebk");
532 validCollation.insert("phonetic");
533 validCollation.insert("pinyin");
534 validCollation.insert("reformed");
535 validCollation.insert("searchjl");
536 validCollation.insert("stroke");
537 validCollation.insert("trad");
538 validCollation.insert("unihan");
539 validCollation.insert("zhuyin");
540 if (validCollation.find(collation) == validCollation.end()) {
541 map["collation"] = "default";
542 }
543 }
544 }
545
GetCollatorOptionValue(napi_env env,napi_value options,std::map<std::string,std::string> & map)546 void GetCollatorOptionValue(napi_env env, napi_value options, std::map<std::string, std::string> &map)
547 {
548 GetCollatorLocaleMatcher(env, options, map);
549 GetCollatorUsage(env, options, map);
550 GetCollatorSensitivity(env, options, map);
551 GetCollatorIgnorePunctuation(env, options, map);
552 GetCollatorNumeric(env, options, map);
553 GetCollatorCaseFirst(env, options, map);
554 GetCollatorCollation(env, options, map);
555 }
556
InitCollator(napi_env env,napi_value exports)557 napi_value IntlAddon::InitCollator(napi_env env, napi_value exports)
558 {
559 napi_property_descriptor properties[] = {
560 DECLARE_NAPI_FUNCTION("compare", CompareString),
561 DECLARE_NAPI_FUNCTION("resolvedOptions", GetCollatorResolvedOptions)
562 };
563
564 napi_value constructor;
565 napi_status status = napi_define_class(env, "Collator", NAPI_AUTO_LENGTH, CollatorConstructor, nullptr,
566 sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor);
567 if (status != napi_ok) {
568 HILOG_ERROR_I18N("Define class failed when InitCollator");
569 return nullptr;
570 }
571
572 status = napi_set_named_property(env, exports, "Collator", constructor);
573 if (status != napi_ok) {
574 HILOG_ERROR_I18N("Set property failed when InitCollator");
575 return nullptr;
576 }
577 return exports;
578 }
579
CollatorConstructor(napi_env env,napi_callback_info info)580 napi_value IntlAddon::CollatorConstructor(napi_env env, napi_callback_info info)
581 {
582 size_t argc = 2;
583 napi_value argv[2] = { nullptr };
584 napi_value thisVar = nullptr;
585 void *data = nullptr;
586 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
587 if (status != napi_ok) {
588 return nullptr;
589 }
590 std::vector<std::string> localeTags;
591 if (argc > 0) {
592 int32_t code = 0;
593 std::vector<std::string> localeArray = JSUtils::GetLocaleArray(env, argv[0], code);
594 if (code != 0) {
595 return nullptr;
596 }
597 localeTags.assign(localeArray.begin(), localeArray.end());
598 }
599 std::map<std::string, std::string> map = {};
600 if (argc > 1) {
601 GetCollatorOptionValue(env, argv[1], map);
602 }
603 std::unique_ptr<IntlAddon> obj = std::make_unique<IntlAddon>();
604 if (obj == nullptr) {
605 return nullptr;
606 }
607 status =
608 napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()), IntlAddon::Destructor, nullptr, nullptr);
609 if (status != napi_ok) {
610 HILOG_ERROR_I18N("CollatorConstructor: Wrap IntlAddon failed");
611 return nullptr;
612 }
613 if (!obj->InitCollatorContext(env, info, localeTags, map)) {
614 HILOG_ERROR_I18N("CollatorConstructor: Init DateTimeFormat failed");
615 return nullptr;
616 }
617 obj.release();
618 return thisVar;
619 }
620
InitCollatorContext(napi_env env,napi_callback_info info,std::vector<std::string> localeTags,std::map<std::string,std::string> & map)621 bool IntlAddon::InitCollatorContext(napi_env env, napi_callback_info info, std::vector<std::string> localeTags,
622 std::map<std::string, std::string> &map)
623 {
624 napi_value global = nullptr;
625 napi_status status = napi_get_global(env, &global);
626 if (status != napi_ok) {
627 HILOG_ERROR_I18N("InitCollatorContext: Get global failed");
628 return false;
629 }
630 env_ = env;
631 collator_ = std::make_unique<Collator>(localeTags, map);
632
633 return collator_ != nullptr;
634 }
635
GetStringParameter(napi_env env,napi_value value,std::vector<char> & buf)636 bool GetStringParameter(napi_env env, napi_value value, std::vector<char> &buf)
637 {
638 napi_valuetype valueType = napi_valuetype::napi_undefined;
639 napi_status status = napi_typeof(env, value, &valueType);
640 if (status != napi_ok) {
641 return false;
642 }
643 if (valueType != napi_valuetype::napi_string) {
644 HILOG_ERROR_I18N("Parameter type does not match");
645 return false;
646 }
647 size_t len = 0;
648 status = napi_get_value_string_utf8(env, value, nullptr, 0, &len);
649 if (status != napi_ok) {
650 HILOG_ERROR_I18N("Get first length failed");
651 return false;
652 }
653 buf.resize(len + 1);
654 status = napi_get_value_string_utf8(env, value, buf.data(), len + 1, &len);
655 if (status != napi_ok) {
656 HILOG_ERROR_I18N("Get first failed");
657 return false;
658 }
659 return true;
660 }
661
FormatRelativeTime(napi_env env,napi_callback_info info)662 napi_value IntlAddon::FormatRelativeTime(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 double number;
673 status = napi_get_value_double(env, argv[0], &number);
674 if (status != napi_ok) {
675 HILOG_ERROR_I18N("FormatRelativeTime: Get number failed");
676 return nullptr;
677 }
678 std::vector<char> unit;
679 if (!GetStringParameter(env, argv[1], unit)) {
680 return nullptr;
681 }
682 IntlAddon *obj = nullptr;
683 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
684 if (status != napi_ok || !obj || !obj->relativetimefmt_) {
685 HILOG_ERROR_I18N("FormatRelativeTime: Get RelativeTimeFormat object failed");
686 return nullptr;
687 }
688 std::string value = obj->relativetimefmt_->Format(number, unit.data());
689 napi_value result = nullptr;
690 status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result);
691 if (status != napi_ok) {
692 HILOG_ERROR_I18N("FormatRelativeTime: Create format string failed");
693 return nullptr;
694 }
695 return result;
696 }
697
FillInArrayElement(napi_env env,napi_value & result,napi_status & status,const std::vector<std::vector<std::string>> & timeVector)698 void IntlAddon::FillInArrayElement(napi_env env, napi_value &result, napi_status &status,
699 const std::vector<std::vector<std::string>> &timeVector)
700 {
701 for (size_t i = 0; i < timeVector.size(); i++) {
702 napi_value value = nullptr;
703 status = napi_create_string_utf8(env, timeVector[i][1].c_str(), NAPI_AUTO_LENGTH, &value);
704 if (status != napi_ok) {
705 HILOG_ERROR_I18N("Failed to create string item imeVector[i][1].");
706 return;
707 }
708 napi_value type = nullptr;
709 status = napi_create_string_utf8(env, timeVector[i][0].c_str(), NAPI_AUTO_LENGTH, &type);
710 if (status != napi_ok) {
711 HILOG_ERROR_I18N("Failed to create string item timeVector[i][0].");
712 return;
713 }
714 napi_value unit = nullptr;
715 size_t unitIndex = 2;
716 if (timeVector[i].size() > unitIndex) {
717 status = napi_create_string_utf8(env, timeVector[i][unitIndex].c_str(), NAPI_AUTO_LENGTH, &unit);
718 if (status != napi_ok) {
719 HILOG_ERROR_I18N("Failed to create string item timeVector[i][unitIndex].");
720 return;
721 }
722 } else {
723 status = napi_get_undefined(env, &unit);
724 if (status != napi_ok) {
725 return;
726 }
727 }
728 std::unordered_map<std::string, napi_value> propertys {
729 { "type", type },
730 { "value", value },
731 { "unit", unit }
732 };
733 int32_t code = 0;
734 napi_value formatInfo = JSUtils::CreateObject(env, propertys, code);
735 if (code != 0) {
736 return;
737 }
738 status = napi_set_element(env, result, i, formatInfo);
739 if (status != napi_ok) {
740 HILOG_ERROR_I18N("Failed to set array item");
741 return;
742 }
743 }
744 }
745
FormatToParts(napi_env env,napi_callback_info info)746 napi_value IntlAddon::FormatToParts(napi_env env, napi_callback_info info)
747 {
748 size_t argc = 2;
749 napi_value argv[2] = { 0 };
750 napi_value thisVar = nullptr;
751 void *data = nullptr;
752 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
753 if (status != napi_ok) {
754 return nullptr;
755 }
756 double number = 0;
757 status = napi_get_value_double(env, argv[0], &number);
758 if (status != napi_ok) {
759 return nullptr;
760 }
761 std::vector<char> unit;
762 if (!GetStringParameter(env, argv[1], unit)) {
763 return nullptr;
764 }
765 IntlAddon *obj = nullptr;
766 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
767 if (status != napi_ok || !obj || !obj->relativetimefmt_) {
768 HILOG_ERROR_I18N("FormatToParts: Get RelativeTimeFormat object failed");
769 return nullptr;
770 }
771 std::vector<std::vector<std::string>> timeVector;
772 obj->relativetimefmt_->FormatToParts(number, unit.data(), timeVector);
773 napi_value result = nullptr;
774 status = napi_create_array_with_length(env, timeVector.size(), &result);
775 if (status != napi_ok) {
776 HILOG_ERROR_I18N("Failed to create array");
777 return nullptr;
778 }
779 FillInArrayElement(env, result, status, timeVector);
780 return result;
781 }
782
CompareString(napi_env env,napi_callback_info info)783 napi_value IntlAddon::CompareString(napi_env env, napi_callback_info info)
784 {
785 size_t argc = 2;
786 napi_value argv[2] = { 0 };
787 napi_value thisVar = nullptr;
788 void *data = nullptr;
789 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
790 if (status != napi_ok) {
791 return nullptr;
792 }
793 std::vector<char> first;
794 if (!GetStringParameter(env, argv[0], first)) {
795 return nullptr;
796 }
797
798 std::vector<char> second;
799 if (!GetStringParameter(env, argv[1], second)) {
800 return nullptr;
801 }
802
803 IntlAddon *obj = nullptr;
804 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
805 if (status != napi_ok || !obj || !obj->collator_) {
806 HILOG_ERROR_I18N("CompareString: Get Collator object failed");
807 return nullptr;
808 }
809
810 CompareResult compareResult = obj->collator_->Compare(first.data(), second.data());
811 napi_value result = nullptr;
812 status = napi_create_int32(env, compareResult, &result);
813 if (status != napi_ok) {
814 HILOG_ERROR_I18N("Create compare result failed");
815 return nullptr;
816 }
817
818 return result;
819 }
820
GetCollatorResolvedOptions(napi_env env,napi_callback_info info)821 napi_value IntlAddon::GetCollatorResolvedOptions(napi_env env, napi_callback_info info)
822 {
823 napi_value thisVar = nullptr;
824 void *data = nullptr;
825 napi_status status = napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data);
826 if (status != napi_ok) {
827 return nullptr;
828 }
829 IntlAddon *obj = nullptr;
830 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
831 if (status != napi_ok || !obj || !obj->collator_) {
832 HILOG_ERROR_I18N("GetCollatorResolvedOptions: Get Collator object failed");
833 return nullptr;
834 }
835 napi_value result = nullptr;
836 status = napi_create_object(env, &result);
837 if (status != napi_ok) {
838 return nullptr;
839 }
840 std::map<std::string, std::string> options = {};
841 obj->collator_->ResolvedOptions(options);
842 JSUtils::SetOptionProperties(env, result, options, "localeMatcher");
843 JSUtils::SetOptionProperties(env, result, options, "locale");
844 JSUtils::SetOptionProperties(env, result, options, "usage");
845 JSUtils::SetOptionProperties(env, result, options, "sensitivity");
846 JSUtils::SetBooleanOptionProperties(env, result, options, "ignorePunctuation");
847 JSUtils::SetBooleanOptionProperties(env, result, options, "numeric");
848 JSUtils::SetOptionProperties(env, result, options, "caseFirst");
849 JSUtils::SetOptionProperties(env, result, options, "collation");
850 return result;
851 }
852
GetPluralRulesType(napi_env env,napi_value options,std::map<std::string,std::string> & map)853 void GetPluralRulesType(napi_env env, napi_value options, std::map<std::string, std::string> &map)
854 {
855 JSUtils::GetOptionValue(env, options, "type", map);
856 auto it = map.find("type");
857 if (it != map.end()) {
858 std::string type = it->second;
859 if (type != "cardinal" && type != "ordinal") {
860 HILOG_ERROR_I18N("invalid type");
861 return;
862 }
863 } else {
864 map.insert(std::make_pair("type", "cardinal"));
865 }
866 }
867
GetPluralRulesInteger(napi_env env,napi_value options,std::map<std::string,std::string> & map)868 void GetPluralRulesInteger(napi_env env, napi_value options, std::map<std::string, std::string> &map)
869 {
870 JSUtils::GetIntegerOptionValue(env, options, "minimumIntegerDigits", map);
871 auto it = map.find("minimumIntegerDigits");
872 if (it != map.end()) {
873 std::string minimumIntegerDigits = it->second;
874 int32_t status = 0;
875 int n = ConvertString2Int(minimumIntegerDigits, status);
876 if (status == -1 || n < 1 || n > 21) { // the valid range of minimumIntegerDigits is [1, 21]
877 HILOG_ERROR_I18N("invalid minimumIntegerDigits");
878 return;
879 }
880 } else {
881 map.insert(std::make_pair("minimumIntegerDigits", std::to_string(1)));
882 }
883 }
884
GetPluralRulesFractions(napi_env env,napi_value options,std::map<std::string,std::string> & map)885 void GetPluralRulesFractions(napi_env env, napi_value options, std::map<std::string, std::string> &map)
886 {
887 JSUtils::GetIntegerOptionValue(env, options, "minimumFractionDigits", map);
888 auto it = map.find("minimumFractionDigits");
889 if (it != map.end()) {
890 std::string minimumFractionDigits = it->second;
891 int32_t status = 0;
892 int n = ConvertString2Int(minimumFractionDigits, status);
893 if (status == -1 || n < 0 || n > 20) { // the valid range of minimumFractionDigits is [0, 20]
894 HILOG_ERROR_I18N("invalid minimumFractionDigits");
895 return;
896 }
897 }
898
899 JSUtils::GetIntegerOptionValue(env, options, "maximumFractionDigits", map);
900 it = map.find("maximumFractionDigits");
901 if (it != map.end()) {
902 std::string maximumFractionDigits = it->second;
903 int32_t status = 0;
904 int n = ConvertString2Int(maximumFractionDigits, status);
905 if (status == -1 || n < 0 || n > 20) { // the valid range of maximumFractionDigits is [0, 20]
906 HILOG_ERROR_I18N("invalid maximumFractionDigits");
907 return;
908 }
909 }
910 }
911
GetPluralRulesSignificant(napi_env env,napi_value options,std::map<std::string,std::string> & map)912 void GetPluralRulesSignificant(napi_env env, napi_value options, std::map<std::string, std::string> &map)
913 {
914 int minSignificant = -1;
915 JSUtils::GetIntegerOptionValue(env, options, "minimumSignificantDigits", map);
916 auto it = map.find("minimumSignificantDigits");
917 if (it != map.end()) {
918 std::string minSignificantStr = it->second;
919 int32_t status = 0;
920 int minSignificantInt = ConvertString2Int(minSignificantStr, status);
921 // the valid range of minSignificantInt is [1, 21]
922 if (status == -1 || minSignificantInt < 1 || minSignificantInt > 21) {
923 HILOG_ERROR_I18N("invalid minimumSignificantDigits");
924 return;
925 }
926 minSignificant = minSignificantInt;
927 } else {
928 minSignificant = 1;
929 }
930
931 JSUtils::GetIntegerOptionValue(env, options, "maximumSignificantDigits", map);
932 it = map.find("maximumSignificantDigits");
933 if (it != map.end()) {
934 std::string maxSignificantStr = it->second;
935 int32_t status = 0;
936 int maxSignificant = ConvertString2Int(maxSignificantStr, status);
937 // the valid range of minSignificant is [minSignificant, 21]
938 if (status == -1 || maxSignificant < minSignificant || maxSignificant > 21) {
939 HILOG_ERROR_I18N("invalid maximumSignificantDigits");
940 return;
941 }
942 }
943 }
944
GetPluralRulesOptionValues(napi_env env,napi_value options,std::map<std::string,std::string> & map)945 void GetPluralRulesOptionValues(napi_env env, napi_value options, std::map<std::string, std::string> &map)
946 {
947 GetCollatorLocaleMatcher(env, options, map);
948 GetPluralRulesType(env, options, map);
949 GetPluralRulesInteger(env, options, map);
950 GetPluralRulesFractions(env, options, map);
951 GetPluralRulesSignificant(env, options, map);
952 }
953
InitPluralRules(napi_env env,napi_value exports)954 napi_value IntlAddon::InitPluralRules(napi_env env, napi_value exports)
955 {
956 napi_property_descriptor properties[] = {
957 DECLARE_NAPI_FUNCTION("select", Select)
958 };
959
960 napi_value constructor = nullptr;
961 napi_status status = napi_define_class(env, "PluralRules", NAPI_AUTO_LENGTH, PluralRulesConstructor, nullptr,
962 sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor);
963 if (status != napi_ok) {
964 HILOG_ERROR_I18N("Define class failed when InitPluralRules");
965 return nullptr;
966 }
967
968 status = napi_set_named_property(env, exports, "PluralRules", constructor);
969 if (status != napi_ok) {
970 HILOG_ERROR_I18N("Set property failed when InitPluralRules");
971 return nullptr;
972 }
973 return exports;
974 }
975
PluralRulesConstructor(napi_env env,napi_callback_info info)976 napi_value IntlAddon::PluralRulesConstructor(napi_env env, napi_callback_info info)
977 {
978 size_t argc = 2;
979 napi_value argv[2] = { nullptr };
980 napi_value thisVar = nullptr;
981 void *data = nullptr;
982 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
983 if (status != napi_ok) {
984 return nullptr;
985 }
986 std::vector<std::string> localeTags;
987 if (argc > 0) {
988 int32_t code = 0;
989 std::vector<std::string> localeArray = JSUtils::GetLocaleArray(env, argv[0], code);
990 if (code != 0) {
991 return nullptr;
992 }
993 localeTags.assign(localeArray.begin(), localeArray.end());
994 }
995 std::map<std::string, std::string> map = {};
996 if (argc > 1) {
997 GetPluralRulesOptionValues(env, argv[1], map);
998 }
999 std::unique_ptr<IntlAddon> obj = std::make_unique<IntlAddon>();
1000 if (obj == nullptr) {
1001 return nullptr;
1002 }
1003 status =
1004 napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()), IntlAddon::Destructor, nullptr, nullptr);
1005 if (status != napi_ok) {
1006 HILOG_ERROR_I18N("PluralRulesConstructor: Wrap IntlAddon failed");
1007 return nullptr;
1008 }
1009 if (!obj->InitPluralRulesContext(env, info, localeTags, map)) {
1010 HILOG_ERROR_I18N("PluralRulesConstructor: Init DateTimeFormat failed");
1011 return nullptr;
1012 }
1013 obj.release();
1014 return thisVar;
1015 }
1016
InitPluralRulesContext(napi_env env,napi_callback_info info,std::vector<std::string> localeTags,std::map<std::string,std::string> & map)1017 bool IntlAddon::InitPluralRulesContext(napi_env env, napi_callback_info info, std::vector<std::string> localeTags,
1018 std::map<std::string, std::string> &map)
1019 {
1020 napi_value global = nullptr;
1021 napi_status status = napi_get_global(env, &global);
1022 if (status != napi_ok) {
1023 HILOG_ERROR_I18N("InitPluralRulesContext: Get global failed");
1024 return false;
1025 }
1026 env_ = env;
1027 pluralrules_ = std::make_unique<PluralRules>(localeTags, map);
1028
1029 return pluralrules_ != nullptr;
1030 }
1031
Select(napi_env env,napi_callback_info info)1032 napi_value IntlAddon::Select(napi_env env, napi_callback_info info)
1033 {
1034 size_t argc = 1;
1035 napi_value argv[1] = { 0 };
1036 napi_value thisVar = nullptr;
1037 void *data = nullptr;
1038 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1039 if (status != napi_ok) {
1040 return nullptr;
1041 }
1042 napi_valuetype valueType = napi_valuetype::napi_undefined;
1043 status = napi_typeof(env, argv[0], &valueType);
1044 if (status != napi_ok) {
1045 return nullptr;
1046 }
1047 if (valueType != napi_valuetype::napi_number) {
1048 HILOG_ERROR_I18N("Select: Parameter type does not match");
1049 return nullptr;
1050 }
1051
1052 double number = 0;
1053 status = napi_get_value_double(env, argv[0], &number);
1054 if (status != napi_ok) {
1055 HILOG_ERROR_I18N("Select: Get number failed");
1056 return nullptr;
1057 }
1058
1059 IntlAddon *obj = nullptr;
1060 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
1061 if (status != napi_ok || !obj || !obj->pluralrules_) {
1062 HILOG_ERROR_I18N("Get PluralRules object failed");
1063 return nullptr;
1064 }
1065
1066 std::string res = obj->pluralrules_->Select(number);
1067 napi_value result = nullptr;
1068 status = napi_create_string_utf8(env, res.c_str(), NAPI_AUTO_LENGTH, &result);
1069 if (status != napi_ok) {
1070 HILOG_ERROR_I18N("get select result failed");
1071 return nullptr;
1072 }
1073 return result;
1074 }
1075
Init(napi_env env,napi_value exports)1076 napi_value IntlAddon::Init(napi_env env, napi_value exports)
1077 {
1078 napi_value val = LocaleInfoAddon::InitLocale(env, exports);
1079 val = IntlAddon::InitDateTimeFormat(env, val);
1080 val = IntlAddon::InitCollator(env, val);
1081 val = IntlAddon::InitRelativeTimeFormat(env, val);
1082 val = IntlAddon::InitPluralRules(env, val);
1083 val = NumberFormatAddon::InitNumberFormat(env, val);
1084 return val;
1085 }
1086 } // namespace I18n
1087 } // namespace Global
1088 } // namespace OHOS
1089
SetBuildInIntlModule(napi_env & env,napi_value & intlModule,napi_value & buildinIntlModule,const std::string & key)1090 bool SetBuildInIntlModule(napi_env &env, napi_value &intlModule, napi_value &buildinIntlModule, const std::string& key)
1091 {
1092 napi_value buildinClass = nullptr;
1093 napi_status status = napi_get_named_property(env, buildinIntlModule, key.c_str(), &buildinClass);
1094 if (status != napi_ok || buildinClass == nullptr) {
1095 HILOG_ERROR_I18N("RegisterIntl: get Buildin Intl class %{public}s failed", key.c_str());
1096 return false;
1097 }
1098 status = napi_set_named_property(env, intlModule, key.c_str(), buildinClass);
1099 if (status != napi_ok) {
1100 HILOG_ERROR_I18N("RegisterIntl: set Buildin Intl class %{public}s failed", key.c_str());
1101 return false;
1102 }
1103 return true;
1104 }
1105
SetBuildInIntl(napi_env & env,napi_value & global,napi_value & intlModule)1106 bool SetBuildInIntl(napi_env &env, napi_value &global, napi_value &intlModule)
1107 {
1108 bool hasProperty = false;
1109 napi_status status = napi_has_named_property(env, global, "Intl", &hasProperty);
1110 if (status != napi_ok || !hasProperty) {
1111 HILOG_ERROR_I18N("RegisterIntl: Has not named Intl property");
1112 return false;
1113 }
1114
1115 napi_value buildinIntlModule = nullptr;
1116 status = napi_get_named_property(env, global, "Intl", &buildinIntlModule);
1117 if (status != napi_ok || buildinIntlModule == nullptr) {
1118 HILOG_ERROR_I18N("RegisterIntl: get Buildin Intl Module failed");
1119 return false;
1120 }
1121
1122 const std::vector<std::string> buildinClasses = {"DurationFormat", "ListFormat", "Locale",
1123 "Segmenter", "getCanonicalLocales", "supportedValuesOf"};
1124
1125 for (std::string buildinClass : buildinClasses) {
1126 if (!SetBuildInIntlModule(env, intlModule, buildinIntlModule, buildinClass)) {
1127 return false;
1128 }
1129 }
1130 return true;
1131 }
1132
BindingIntlModules(napi_env env,napi_value & intlModule)1133 bool BindingIntlModules(napi_env env, napi_value &intlModule)
1134 {
1135 intlModule = OHOS::Global::I18n::CollatorAddon::InitCollator(env, intlModule);
1136 if (intlModule == nullptr) {
1137 HILOG_ERROR_I18N("RegisterIntl: init Intl Collator Module failed");
1138 return false;
1139 }
1140 intlModule = OHOS::Global::I18n::DisplayNamesAddon::InitDisplayNames(env, intlModule);
1141 if (intlModule == nullptr) {
1142 HILOG_ERROR_I18N("RegisterIntl: init Intl DisplayNames Module failed");
1143 return false;
1144 }
1145 intlModule = OHOS::Global::I18n::JSNumberFormatAddon::InitJsNumberFormat(env, intlModule);
1146 if (intlModule == nullptr) {
1147 HILOG_ERROR_I18N("RegisterIntl: init Intl NumberFormat Module failed");
1148 return false;
1149 }
1150 intlModule = OHOS::Global::I18n::IntlDateTimeFormatAddon::InitIntlDateTimeFormat(env, intlModule);
1151 if (intlModule == nullptr) {
1152 HILOG_ERROR_I18N("RegisterIntl: init Intl DateTimeFormat Module failed");
1153 return false;
1154 }
1155 intlModule = OHOS::Global::I18n::IntlPluralRulesAddon::InitIntlPluralRules(env, intlModule);
1156 if (intlModule == nullptr) {
1157 HILOG_ERROR_I18N("RegisterIntl: init Intl PluralRules Module failed");
1158 return false;
1159 }
1160 intlModule = OHOS::Global::I18n::JSRelativeTimeFormatAddon::InitJsRelativeTimeFormat(env, intlModule);
1161 if (intlModule == nullptr) {
1162 HILOG_ERROR_I18N("RegisterIntl: init Intl RelativeTimeFormat Module failed");
1163 return false;
1164 }
1165 return true;
1166 }
1167
RegisterIntl(napi_env env)1168 bool RegisterIntl(napi_env env)
1169 {
1170 if (env == nullptr) {
1171 HILOG_ERROR_I18N("RegisterIntl: env is null");
1172 return false;
1173 }
1174
1175 napi_value global = nullptr;
1176 napi_status status = napi_get_global(env, &global);
1177 if (status != napi_ok || global == nullptr) {
1178 HILOG_ERROR_I18N("RegisterIntl: get global obj failed");
1179 return false;
1180 }
1181
1182 napi_value intlModule = nullptr;
1183 status = napi_create_object(env, &intlModule);
1184 if (status != napi_ok) {
1185 HILOG_ERROR_I18N("RegisterIntl: Define Intl object failed.");
1186 return false;
1187 }
1188
1189 if (!BindingIntlModules(env, intlModule)) {
1190 return false;
1191 }
1192
1193 if (!SetBuildInIntl(env, global, intlModule)) {
1194 return false;
1195 }
1196
1197 status = napi_set_named_property(env, global, "Intl", intlModule);
1198 if (status != napi_ok) {
1199 HILOG_ERROR_I18N("RegisterIntl: Set property failed when Init Intl module.");
1200 return false;
1201 }
1202 HILOG_INFO_I18N("RegisterIntl: Replace buildin Intl Success.");
1203 return true;
1204 }
1205