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