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