1 /*
2 * Copyright (c) 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 "displaynames_addon.h"
16
17 #include "error_util.h"
18 #include "intl_addon.h"
19 #include "i18n_hilog.h"
20 #include "js_utils.h"
21
22 namespace OHOS {
23 namespace Global {
24 namespace I18n {
DisplayNamesAddon()25 DisplayNamesAddon::DisplayNamesAddon() : env_(nullptr) {}
26
~DisplayNamesAddon()27 DisplayNamesAddon::~DisplayNamesAddon()
28 {
29 }
30
Destructor(napi_env env,void * nativeObject,void * hint)31 void DisplayNamesAddon::Destructor(napi_env env, void *nativeObject, void *hint)
32 {
33 if (!nativeObject) {
34 return;
35 }
36 delete reinterpret_cast<DisplayNamesAddon *>(nativeObject);
37 nativeObject = nullptr;
38 }
39
InitDisplayNames(napi_env env,napi_value exports)40 napi_value DisplayNamesAddon::InitDisplayNames(napi_env env, napi_value exports)
41 {
42 napi_property_descriptor properties[] = {
43 DECLARE_NAPI_FUNCTION("of", Of),
44 DECLARE_NAPI_FUNCTION("resolvedOptions", ResolvedOptions),
45 DECLARE_NAPI_STATIC_FUNCTION("supportedLocalesOf", SupportedLocalesOf),
46 };
47
48 napi_value constructor;
49 napi_status status = napi_define_class(env, "DisplayNames", NAPI_AUTO_LENGTH, DisplayNamesConstructor, nullptr,
50 sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor);
51 if (status != napi_ok) {
52 HILOG_ERROR_I18N("InitDisplayNames: Define class failed when InitDisplayNames");
53 return nullptr;
54 }
55
56 status = napi_set_named_property(env, exports, "DisplayNames", constructor);
57 if (status != napi_ok) {
58 HILOG_ERROR_I18N("InitDisplayNames: Set property failed when InitDisplayNames");
59 return nullptr;
60 }
61 return exports;
62 }
63
DisplayNamesConstructor(napi_env env,napi_callback_info info)64 napi_value DisplayNamesAddon::DisplayNamesConstructor(napi_env env, napi_callback_info info)
65 {
66 size_t argc = 2;
67 napi_value argv[2] = { nullptr };
68 napi_value thisVar = nullptr;
69 void *data = nullptr;
70 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
71 if (status != napi_ok) {
72 HILOG_ERROR_I18N("DisplayNamesConstructor: napi get callback info failed.");
73 return nullptr;
74 }
75 std::vector<std::string> localeTags;
76 if (argc < 2) { // 2 indicates the number of parameters
77 HILOG_ERROR_I18N("DisplayNamesConstructor: Two arguments are needed, but only get %{public}zu.", argc);
78 ErrorUtil::NapiThrowUndefined(env, "options is undefined");
79 return nullptr;
80 }
81 int32_t code = 0;
82 std::vector<std::string> localeArray = JSUtils::GetLocaleArray(env, argv[0], code);
83 localeTags.assign(localeArray.begin(), localeArray.end());
84 std::map<std::string, std::string> map = {};
85 GetOptionValues(env, argv[1], map);
86 DisplayNamesAddon* obj = new(std::nothrow) DisplayNamesAddon();
87 if (obj == nullptr) {
88 HILOG_ERROR_I18N("DisplayNamesConstructor: make unique ptr failed.");
89 return nullptr;
90 }
91 status =
92 napi_wrap(env, thisVar, reinterpret_cast<void *>(obj), DisplayNamesAddon::Destructor, nullptr, nullptr);
93 if (status != napi_ok) {
94 HILOG_ERROR_I18N("DisplayNamesConstructor: Wrap DisplayNamesAddon failed");
95 delete obj;
96 return nullptr;
97 }
98 if (!obj->InitDisplayNamesContext(env, info, localeTags, map)) {
99 return nullptr;
100 }
101 return thisVar;
102 }
103
InitDisplayNamesContext(napi_env env,napi_callback_info info,const std::vector<std::string> & localeTags,const std::map<std::string,std::string> & map)104 bool DisplayNamesAddon::InitDisplayNamesContext(napi_env env, napi_callback_info info,
105 const std::vector<std::string> &localeTags, const std::map<std::string, std::string> &map)
106 {
107 env_ = env;
108 displaynames_ = std::make_unique<DisplayNames>(localeTags, map);
109 if (displaynames_ == nullptr) {
110 HILOG_ERROR_I18N("InitDisplayNamesContext: make_unique DisplayNames failed");
111 return false;
112 }
113 I18nErrorCode errorCode = displaynames_->GetError();
114 if (errorCode == I18nErrorCode::MISSING_PARAM) {
115 HILOG_ERROR_I18N("InitDisplayNamesContext: MISSING_PARAM failed");
116 ErrorUtil::NapiThrowUndefined(env, "type is undefined");
117 return false;
118 } else if (errorCode == I18nErrorCode::INVALID_PARAM) {
119 HILOG_ERROR_I18N("InitDisplayNamesContext: INVALID_PARAM failed");
120 ErrorUtil::NapiThrowUndefined(env, "getStringOption failed");
121 return false;
122 } else if (errorCode == I18nErrorCode::INVALID_LOCALE_TAG) {
123 HILOG_ERROR_I18N("InitDisplayNamesContext: invalid locale");
124 ErrorUtil::NapiThrowUndefined(env, "invalid locale");
125 return false;
126 }
127 return errorCode == I18nErrorCode::SUCCESS;
128 }
129
SupportedLocalesOf(napi_env env,napi_callback_info info)130 napi_value DisplayNamesAddon::SupportedLocalesOf(napi_env env, napi_callback_info info)
131 {
132 size_t argc = 2;
133 napi_value argv[2] = { nullptr };
134 napi_value thisVar = nullptr;
135 void *data = nullptr;
136 std::vector<std::string> resultLocales = {};
137 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
138 if (status != napi_ok) {
139 HILOG_ERROR_I18N("DisplayNamesAddon::SupportedLocalesOf: napi get callback info failed.");
140 return JSUtils::CreateArray(env, resultLocales);
141 }
142 std::vector<std::string> localeTags;
143 if (argc > 0) {
144 int32_t code = 0;
145 std::vector<std::string> localeArray = JSUtils::GetLocaleArray(env, argv[0], code);
146 if (code != 0) {
147 HILOG_ERROR_I18N("DisplayNamesAddon::SupportedLocalesOf: JSUtils:GetLocaleArray failed.");
148 ErrorUtil::NapiThrowUndefined(env, "kValue is not String or Object");
149 return JSUtils::CreateArray(env, resultLocales);
150 }
151 localeTags.assign(localeArray.begin(), localeArray.end());
152 }
153 std::map<std::string, std::string> map = {};
154 if (argc > 1) {
155 JSUtils::GetOptionValue(env, argv[1], "localeMatcher", map);
156 }
157 I18nErrorCode i18nStatus = I18nErrorCode::SUCCESS;
158 resultLocales = DisplayNames::SupportedLocalesOf(localeTags, map, i18nStatus);
159 if (i18nStatus == I18nErrorCode::INVALID_PARAM) {
160 HILOG_ERROR_I18N("DisplayNamesAddon::SupportedLocalesOf: SupportedLocalesOf invalid param");
161 ErrorUtil::NapiThrowUndefined(env, "getStringOption failed");
162 } else if (i18nStatus == I18nErrorCode::INVALID_LOCALE_TAG) {
163 HILOG_ERROR_I18N("DisplayNamesAddon::SupportedLocalesOf: SupportedLocalesOf invalid locale");
164 ErrorUtil::NapiThrowUndefined(env, "invalid locale");
165 }
166 return JSUtils::CreateArray(env, resultLocales);
167 }
168
Of(napi_env env,napi_callback_info info)169 napi_value DisplayNamesAddon::Of(napi_env env, napi_callback_info info)
170 {
171 size_t argc = 1;
172 napi_value argv[1] = { nullptr };
173 napi_value thisVar = nullptr;
174 void *data = nullptr;
175 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
176 if (status != napi_ok) {
177 HILOG_ERROR_I18N("DisplayNamesAddon::Of: napi get callback info failed.");
178 return JSUtils::CreateEmptyString(env);
179 }
180 if (argc < 1) {
181 HILOG_ERROR_I18N("DisplayNamesAddon::Of: missing code param.");
182 ErrorUtil::NapiThrowUndefined(env, "code is undefined");
183 return JSUtils::CreateEmptyString(env);
184 }
185 int32_t errorCode = 0;
186 std::string code = JSUtils::GetString(env, argv[0], errorCode);
187 if (errorCode != 0) {
188 return JSUtils::CreateEmptyString(env);
189 }
190
191 DisplayNamesAddon *obj = nullptr;
192 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
193 if (status != napi_ok || !obj || !obj->displaynames_) {
194 HILOG_ERROR_I18N("DisplayNamesAddon::Of: Get DisplayNames object failed");
195 return JSUtils::CreateEmptyString(env);
196 }
197 std::string displayResult = obj->displaynames_->Display(code);
198 I18nErrorCode i18nErrorCode = obj->displaynames_->GetError();
199 if (i18nErrorCode != I18nErrorCode::SUCCESS) {
200 std::string errorMessage = obj->displaynames_->GetErrorMessage();
201 HILOG_ERROR_I18N("DisplayNamesAddon::Of: %{public}s.", errorMessage.c_str());
202 ErrorUtil::NapiThrowUndefined(env, errorMessage);
203 return JSUtils::CreateEmptyString(env);
204 }
205 return JSUtils::CreateString(env, displayResult);
206 }
207
ResolvedOptions(napi_env env,napi_callback_info info)208 napi_value DisplayNamesAddon::ResolvedOptions(napi_env env, napi_callback_info info)
209 {
210 napi_value result = nullptr;
211 napi_status status = napi_create_object(env, &result);
212 if (status != napi_ok) {
213 return JSUtils::CreateEmptyObject(env);
214 }
215
216 napi_value thisVar = nullptr;
217 void *data = nullptr;
218 status = napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data);
219 if (status != napi_ok) {
220 return result;
221 }
222 DisplayNamesAddon *obj = nullptr;
223 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
224 if (status != napi_ok || !obj || !obj->displaynames_) {
225 HILOG_ERROR_I18N("DisplayNamesAddon::ResolvedOptions: Get DisplayNames object failed");
226 return result;
227 }
228 std::map<std::string, std::string> options = obj->displaynames_->ResolvedOptions();
229 JSUtils::SetOptionProperties(env, result, options, "locale");
230 JSUtils::SetOptionProperties(env, result, options, "style");
231 JSUtils::SetOptionProperties(env, result, options, "type");
232 JSUtils::SetOptionProperties(env, result, options, "fallback");
233 JSUtils::SetOptionProperties(env, result, options, "languageDisplay");
234 return result;
235 }
236
GetOptionValues(napi_env env,napi_value options,std::map<std::string,std::string> & map)237 void DisplayNamesAddon::GetOptionValues(napi_env env, napi_value options, std::map<std::string, std::string> &map)
238 {
239 JSUtils::GetOptionValue(env, options, "localeMatcher", map);
240 JSUtils::GetOptionValue(env, options, "style", map);
241 JSUtils::GetOptionValue(env, options, "type", map);
242 JSUtils::GetOptionValue(env, options, "fallback", map);
243 JSUtils::GetOptionValue(env, options, "languageDisplay", map);
244 }
245 } // namespace I18n
246 } // namespace Global
247 } // namespace OHOS