• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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