1 /*
2 * Copyright (c) 2023 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
16 #include "error_util.h"
17 #include "hilog/log.h"
18 #include "locale_config.h"
19 #include "variable_convertor.h"
20 #include "system_locale_manager_addon.h"
21
22 namespace OHOS {
23 namespace Global {
24 namespace I18n {
25 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, 0xD001E00, "SystemLocaleManagerJs" };
26 using namespace OHOS::HiviewDFX;
27
SystemLocaleManagerAddon()28 SystemLocaleManagerAddon::SystemLocaleManagerAddon() : env_(nullptr) {}
29
~SystemLocaleManagerAddon()30 SystemLocaleManagerAddon::~SystemLocaleManagerAddon()
31 {
32 }
33
Destructor(napi_env env,void * nativeObject,void * hint)34 void SystemLocaleManagerAddon::Destructor(napi_env env, void *nativeObject, void *hint)
35 {
36 if (!nativeObject) {
37 return;
38 }
39 delete reinterpret_cast<SystemLocaleManagerAddon *>(nativeObject);
40 nativeObject = nullptr;
41 }
42
InitSystemLocaleManager(napi_env env,napi_value exports)43 napi_value SystemLocaleManagerAddon::InitSystemLocaleManager(napi_env env, napi_value exports)
44 {
45 napi_status status = napi_ok;
46 napi_property_descriptor properties[] = {
47 DECLARE_NAPI_FUNCTION("getLanguageInfoArray", GetLanguageInfoArray),
48 DECLARE_NAPI_FUNCTION("getRegionInfoArray", GetCountryInfoArray),
49 DECLARE_NAPI_STATIC_FUNCTION("getTimeZoneCityItemArray", GetTimeZoneCityInfoArray)
50 };
51
52 napi_value constructor = nullptr;
53 status = napi_define_class(env, "SystemLocaleManager", NAPI_AUTO_LENGTH, SystemLocaleManagerConstructor, nullptr,
54 sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor);
55 if (status != napi_ok) {
56 HiLog::Error(LABEL, "Define class failed when InitSystemLocaleManager");
57 return nullptr;
58 }
59
60 status = napi_set_named_property(env, exports, "SystemLocaleManager", constructor);
61 if (status != napi_ok) {
62 HiLog::Error(LABEL, "Set property failed when InitSystemLocaleManager");
63 return nullptr;
64 }
65 return exports;
66 }
67
SystemLocaleManagerConstructor(napi_env env,napi_callback_info info)68 napi_value SystemLocaleManagerAddon::SystemLocaleManagerConstructor(napi_env env, napi_callback_info info)
69 {
70 napi_value thisVar = nullptr;
71 void *data = nullptr;
72 napi_status status = napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data);
73 if (status != napi_ok) {
74 return nullptr;
75 }
76 std::unique_ptr<SystemLocaleManagerAddon> obj = std::make_unique<SystemLocaleManagerAddon>();
77 status = napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()), SystemLocaleManagerAddon::Destructor,
78 nullptr, nullptr);
79 if (status != napi_ok) {
80 HiLog::Error(LABEL, "Wrap SystemLocaleManagerAddon failed");
81 return nullptr;
82 }
83 if (!obj->InitSystemLocaleManagerContext(env, info)) {
84 HiLog::Error(LABEL, "Init SystemLocaleManager failed");
85 return nullptr;
86 }
87 obj.release();
88 return thisVar;
89 }
90
InitSystemLocaleManagerContext(napi_env env,napi_callback_info info)91 bool SystemLocaleManagerAddon::InitSystemLocaleManagerContext(napi_env env, napi_callback_info info)
92 {
93 napi_value global = nullptr;
94 napi_status status = napi_get_global(env, &global);
95 if (status != napi_ok) {
96 HiLog::Error(LABEL, "Get global failed");
97 return false;
98 }
99 env_ = env;
100 systemLocaleManager_ = std::make_unique<SystemLocaleManager>();
101
102 return systemLocaleManager_ != nullptr;
103 }
104
GetLanguageInfoArray(napi_env env,napi_callback_info info)105 napi_value SystemLocaleManagerAddon::GetLanguageInfoArray(napi_env env, napi_callback_info info)
106 {
107 size_t argc = 2;
108 napi_value argv[2] = { 0 };
109 napi_value thisVar = nullptr;
110 void *data = nullptr;
111 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
112 if (status != napi_ok) {
113 HiLog::Error(LABEL, "can not obtain getLanguageInfoArray function param.");
114 ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, true);
115 return nullptr;
116 }
117 std::vector<std::string> languageList;
118 bool isSuccess = VariableConvertor::GetStringArrayFromJsParam(env, argv[0], languageList);
119 if (!isSuccess) {
120 return nullptr;
121 }
122 SortOptions options;
123 GetSortOptionsFromJsParam(env, argv[1], options, false);
124 SystemLocaleManagerAddon *obj = nullptr;
125 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
126 if (status != napi_ok || !obj || !obj->systemLocaleManager_) {
127 HiLog::Error(LABEL, "Get SystemLocaleManager object failed");
128 return nullptr;
129 }
130 std::vector<LocaleItem> localeItemList = obj->systemLocaleManager_->GetLanguageInfoArray(languageList, options);
131 napi_value result = CreateLocaleItemArray(env, localeItemList);
132 return result;
133 }
134
GetCountryInfoArray(napi_env env,napi_callback_info info)135 napi_value SystemLocaleManagerAddon::GetCountryInfoArray(napi_env env, napi_callback_info info)
136 {
137 size_t argc = 2;
138 napi_value argv[2] = { 0 };
139 napi_value thisVar = nullptr;
140 void *data = nullptr;
141 napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
142 if (status != napi_ok) {
143 HiLog::Error(LABEL, "can not obtain getCountryInfoArray function param.");
144 ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, true);
145 return nullptr;
146 }
147 std::vector<std::string> countryList;
148 bool isSuccess = VariableConvertor::GetStringArrayFromJsParam(env, argv[0], countryList);
149 if (!isSuccess) {
150 return nullptr;
151 }
152 SortOptions options;
153 GetSortOptionsFromJsParam(env, argv[1], options, true);
154 SystemLocaleManagerAddon *obj = nullptr;
155 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
156 if (status != napi_ok || !obj || !obj->systemLocaleManager_) {
157 HiLog::Error(LABEL, "Get SystemLocaleManager object failed");
158 return nullptr;
159 }
160 std::vector<LocaleItem> localeItemList = obj->systemLocaleManager_->GetCountryInfoArray(countryList, options);
161 napi_value result = CreateLocaleItemArray(env, localeItemList);
162 return result;
163 }
164
GetTimeZoneCityInfoArray(napi_env env,napi_callback_info info)165 napi_value SystemLocaleManagerAddon::GetTimeZoneCityInfoArray(napi_env env, napi_callback_info info)
166 {
167 std::vector<TimeZoneCityItem> timezoneCityItemList = SystemLocaleManager::GetTimezoneCityInfoArray();
168 napi_value result = nullptr;
169 napi_status status = napi_create_array_with_length(env, timezoneCityItemList.size(), &result);
170 if (status != napi_ok) {
171 HiLog::Error(LABEL, "create TimeZoneCityItem array failed.");
172 return nullptr;
173 }
174 for (size_t i = 0; i < timezoneCityItemList.size(); ++i) {
175 napi_value item = CreateTimeZoneCityItem(env, timezoneCityItemList[i]);
176 status = napi_set_element(env, result, i, item);
177 if (status != napi_ok) {
178 HiLog::Error(LABEL, "Failed to set TimeZoneCityItem element.");
179 return nullptr;
180 }
181 }
182 return result;
183 }
184
CreateTimeZoneCityItem(napi_env env,const TimeZoneCityItem & timezoneCityItem)185 napi_value SystemLocaleManagerAddon::CreateTimeZoneCityItem(napi_env env, const TimeZoneCityItem &timezoneCityItem)
186 {
187 napi_value result;
188 napi_status status = napi_create_object(env, &result);
189 if (status != napi_ok) {
190 HiLog::Error(LABEL, "Create Locale Item object failed.");
191 return nullptr;
192 }
193 status = napi_set_named_property(env, result, "zoneId",
194 VariableConvertor::CreateString(env, timezoneCityItem.zoneId));
195 if (status != napi_ok) {
196 HiLog::Error(LABEL, "Failed to set element zoneId.");
197 return nullptr;
198 }
199 status = napi_set_named_property(env, result, "cityId",
200 VariableConvertor::CreateString(env, timezoneCityItem.cityId));
201 if (status != napi_ok) {
202 HiLog::Error(LABEL, "Failed to set element cityId.");
203 return nullptr;
204 }
205 status = napi_set_named_property(env, result, "cityDisplayName",
206 VariableConvertor::CreateString(env, timezoneCityItem.cityDisplayName));
207 if (status != napi_ok) {
208 HiLog::Error(LABEL, "Failed to set element cityDisplayName.");
209 return nullptr;
210 }
211 status = napi_set_named_property(env, result, "offset",
212 VariableConvertor::CreateNumber(env, timezoneCityItem.offset));
213 if (status != napi_ok) {
214 HiLog::Error(LABEL, "Failed to set element offset.");
215 return nullptr;
216 }
217 status = napi_set_named_property(env, result, "zoneDisplayName",
218 VariableConvertor::CreateString(env, timezoneCityItem.zoneDisplayName));
219 if (status != napi_ok) {
220 HiLog::Error(LABEL, "Failed to set element zoneDisplayName.");
221 return nullptr;
222 }
223 if (timezoneCityItem.rawOffset != 0) {
224 status = napi_set_named_property(env, result, "rawOffset",
225 VariableConvertor::CreateNumber(env, timezoneCityItem.rawOffset));
226 if (status != napi_ok) {
227 HiLog::Error(LABEL, "Failed to set element rawOffset.");
228 return nullptr;
229 }
230 }
231 return result;
232 }
233
GetSortOptionsFromJsParam(napi_env env,napi_value & jsOptions,SortOptions & options,bool isRegion)234 void SystemLocaleManagerAddon::GetSortOptionsFromJsParam(napi_env env, napi_value &jsOptions, SortOptions &options,
235 bool isRegion)
236 {
237 std::string localeTag;
238 bool isUseLocalName = true;
239 bool isSuggestedFirst = true;
240 if (jsOptions == nullptr) {
241 localeTag = LocaleConfig::GetSystemLocale();
242 if (isRegion) {
243 isUseLocalName = false;
244 }
245 } else {
246 VariableConvertor::GetOptionValue(env, jsOptions, "locale", localeTag);
247 if (localeTag.length() == 0) {
248 localeTag = LocaleConfig::GetSystemLocale();
249 }
250 bool isSuccess = VariableConvertor::GetBoolOptionValue(env, jsOptions, "isUseLocalName", isUseLocalName);
251 if (!isSuccess && isRegion) {
252 isUseLocalName = false;
253 }
254 VariableConvertor::GetBoolOptionValue(env, jsOptions, "isSuggestedFirst", isSuggestedFirst);
255 }
256 options.localeTag = localeTag;
257 options.isUseLocalName = isUseLocalName;
258 options.isSuggestedFirst = isSuggestedFirst;
259 }
260
CreateLocaleItemArray(napi_env env,const std::vector<LocaleItem> & localeItemList)261 napi_value SystemLocaleManagerAddon::CreateLocaleItemArray(napi_env env, const std::vector<LocaleItem> &localeItemList)
262 {
263 napi_value result = nullptr;
264 napi_status status = napi_create_array_with_length(env, localeItemList.size(), &result);
265 if (status != napi_ok) {
266 HiLog::Error(LABEL, "create LocaleItem array failed.");
267 return nullptr;
268 }
269 for (size_t i = 0; i < localeItemList.size(); ++i) {
270 napi_value item = CreateLocaleItem(env, localeItemList[i]);
271 status = napi_set_element(env, result, i, item);
272 if (status != napi_ok) {
273 HiLog::Error(LABEL, "Failed to set LocaleItem element.");
274 return nullptr;
275 }
276 }
277 return result;
278 }
279
CreateLocaleItem(napi_env env,const LocaleItem & localeItem)280 napi_value SystemLocaleManagerAddon::CreateLocaleItem(napi_env env, const LocaleItem &localeItem)
281 {
282 napi_value result;
283 napi_status status = napi_create_object(env, &result);
284 if (status != napi_ok) {
285 HiLog::Error(LABEL, "Create Locale Item object failed.");
286 return nullptr;
287 }
288 status = napi_set_named_property(env, result, "id", VariableConvertor::CreateString(env, localeItem.id));
289 if (status != napi_ok) {
290 HiLog::Error(LABEL, "Failed to set element id.");
291 return nullptr;
292 }
293 status = napi_set_named_property(env, result, "displayName",
294 VariableConvertor::CreateString(env, localeItem.displayName));
295 if (status != napi_ok) {
296 HiLog::Error(LABEL, "Failed to set element displayName.");
297 return nullptr;
298 }
299 if (localeItem.localName.length() != 0) {
300 status = napi_set_named_property(env, result, "localName",
301 VariableConvertor::CreateString(env, localeItem.localName));
302 if (status != napi_ok) {
303 HiLog::Error(LABEL, "Failed to set element localName.");
304 return nullptr;
305 }
306 }
307 status = napi_set_named_property(env, result, "suggestionType", CreateSuggestionType(env,
308 localeItem.suggestionType));
309 if (status != napi_ok) {
310 HiLog::Error(LABEL, "Failed to set element suggestionType.");
311 return nullptr;
312 }
313 return result;
314 }
315
CreateSuggestionType(napi_env env,SuggestionType suggestionType)316 napi_value SystemLocaleManagerAddon::CreateSuggestionType(napi_env env, SuggestionType suggestionType)
317 {
318 napi_value result;
319 napi_status status = napi_create_int32(env, static_cast<int32_t>(suggestionType), &result);
320 if (status != napi_ok) {
321 HiLog::Error(LABEL, "create SuggestionType failed.");
322 return nullptr;
323 }
324 return result;
325 }
326 } // namespace I18n
327 } // namespace Global
328 } // namespace OHOS