1 /*
2 * Copyright (c) 2021-2022 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 <regex>
16 #include "accesstoken_kit.h"
17 #ifdef SUPPORT_GRAPHICS
18 #include "app_mgr_client.h"
19 #include "ability_manager_client.h"
20 #include "configuration.h"
21 #include <common_event_data.h>
22 #include <common_event_manager.h>
23 #include <common_event_publish_info.h>
24 #include <common_event_support.h>
25 #endif
26 #include <cctype>
27 #include "hilog/log.h"
28 #include "ipc_skeleton.h"
29 #include "libxml/parser.h"
30 #include "locale_info.h"
31 #include "localebuilder.h"
32 #include "locdspnm.h"
33 #include "locid.h"
34 #include "ohos/init_data.h"
35 #include "parameter.h"
36 #include "securec.h"
37 #include "string_ex.h"
38 #include "ucase.h"
39 #include "ulocimp.h"
40 #include "unistr.h"
41 #include "ureslocs.h"
42 #include "ustring.h"
43 #include "ustr_imp.h"
44 #include "utils.h"
45 #include "tokenid_kit.h"
46 #include "locale_config.h"
47
48 namespace OHOS {
49 namespace Global {
50 namespace I18n {
51 using namespace std;
52 using namespace OHOS::HiviewDFX;
53
54 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, 0xD001E00, "LocaleConfig" };
55 const char *LocaleConfig::LANGUAGE_KEY = "persist.global.language";
56 const char *LocaleConfig::LOCALE_KEY = "persist.global.locale";
57 const char *LocaleConfig::HOUR_KEY = "persist.global.is24Hour";
58 const char *LocaleConfig::DEFAULT_LOCALE_KEY = "const.global.locale";
59 const char *LocaleConfig::DEFAULT_LANGUAGE_KEY = "const.global.language";
60 const char *LocaleConfig::DEFAULT_REGION_KEY = "const.global.region";
61 const char *LocaleConfig::SIM_COUNTRY_CODE_KEY = "telephony.sim.countryCode0";
62 const char *LocaleConfig::SUPPORTED_LOCALES_NAME = "supported_locales";
63 const char *LocaleConfig::SUPPORTED_REGIONS_NAME = "supported_regions";
64 const char *LocaleConfig::WHITE_LANGUAGES_NAME = "white_languages";
65 const char *LocaleConfig::FORBIDDEN_LANGUAGES_NAME = "forbidden_languages";
66 const char *LocaleConfig::FORBIDDEN_REGIONS_NAME = "forbidden_regions";
67 const char *LocaleConfig::FORBIDDEN_LANGUAGES_PATH = "/system/usr/ohos_locale_config/forbidden_languages.xml";
68 const char *LocaleConfig::FORBIDDEN_REGIONS_PATH = "/system/usr/ohos_locale_config/forbidden_regions.xml";
69 const char *LocaleConfig::SUPPORTED_LOCALES_PATH = "/system/usr/ohos_locale_config/supported_locales.xml";
70 const char *LocaleConfig::SUPPORTED_REGIONS_PATH = "/system/usr/ohos_locale_config/supported_regions.xml";
71 const char *LocaleConfig::WHITE_LANGUAGES_PATH = "/system/usr/ohos_locale_config/white_languages.xml";
72 const char *LocaleConfig::SUPPORT_LOCALES_PATH = "/etc/ohos_lang_config/supported_locales.xml";
73 const char *LocaleConfig::SUPPORT_LOCALES_NAME = "supported_locales";
74 const char *LocaleConfig::DIALECT_LANGS_PATH = "/system/usr/ohos_locale_config/dialect_languages.xml";
75 const char *LocaleConfig::DIALECT_LANGS_NAME = "dialect_langs";
76 const char *LocaleConfig::OVERRIDE_SUPPORTED_REGIONS_NAME = "supported_regions";
77 const char *LocaleConfig::OVERRIDE_SUPPORTED_REGIONS_PATH =
78 "/system/usr/ohos_locale_config/region/supported_regions.xml";
79 const char *LocaleConfig::DEFAULT_LOCALE = "en-Latn";
80 const char *LocaleConfig::supportLocalesTag = "supported_locales";
81 const char *LocaleConfig::LANG_PATH = "/etc/ohos_lang_config/";
82 const char *LocaleConfig::REGION_PATH = "/system/usr/ohos_locale_config/region/";
83 const char *LocaleConfig::rootTag = "languages";
84 const char *LocaleConfig::secondRootTag = "lang";
85 const char *LocaleConfig::rootRegion = "regions";
86 const char *LocaleConfig::secondRootRegion = "region";
87 unordered_set<string> LocaleConfig::supportedLocales;
88 unordered_set<string> LocaleConfig::supportLocales;
89 unordered_set<string> LocaleConfig::supportedRegions;
90 unordered_set<string> LocaleConfig::overrideSupportedRegions;
91 unordered_set<string> LocaleConfig::dialectLang;
92 unordered_set<string> LocaleConfig::blockedLanguages;
93 unordered_set<string> LocaleConfig::blockedRegions;
94 unordered_map<string, unordered_set<string>> LocaleConfig::blockedLanguageRegions;
95 unordered_set<string> LocaleConfig::whiteLanguages;
96 unordered_map<string, string> LocaleConfig::dialectMap {
97 { "es-Latn-419", "es-Latn-419" },
98 { "es-Latn-BO", "es-Latn-419" },
99 { "es-Latn-BR", "es-Latn-419" },
100 { "es-Latn-BZ", "es-Latn-419" },
101 { "es-Latn-CL", "es-Latn-419" },
102 { "es-Latn-CO", "es-Latn-419" },
103 { "es-Latn-CR", "es-Latn-419" },
104 { "es-Latn-CU", "es-Latn-419" },
105 { "es-Latn-DO", "es-Latn-419" },
106 { "es-Latn-EC", "es-Latn-419" },
107 { "es-Latn-GT", "es-Latn-419" },
108 { "es-Latn-HN", "es-Latn-419" },
109 { "es-Latn-MX", "es-Latn-419" },
110 { "es-Latn-NI", "es-Latn-419" },
111 { "es-Latn-PA", "es-Latn-419" },
112 { "es-Latn-PE", "es-Latn-419" },
113 { "es-Latn-PR", "es-Latn-419" },
114 { "es-Latn-PY", "es-Latn-419" },
115 { "es-Latn-SV", "es-Latn-419" },
116 { "es-Latn-US", "es-Latn-419" },
117 { "es-Latn-UY", "es-Latn-419" },
118 { "es-Latn-VE", "es-Latn-419" },
119 { "pt-Latn-PT", "pt-Latn-PT" },
120 { "en-Latn-US", "en-Latn-US" }
121 };
122
123 unordered_map<string, string> LocaleConfig::localDigitMap {
124 { "ar", "arab" },
125 { "as", "beng" },
126 { "bn", "beng" },
127 { "fa", "arabext" },
128 { "mr", "deva" },
129 { "my", "mymr" },
130 { "ne", "deva" },
131 { "ur", "latn" }
132 };
133
134 std::map<std::string, std::string> LocaleConfig::supportedDialectLocales;
135 std::map<string, string> LocaleConfig::locale2DisplayName {};
136 std::map<string, string> LocaleConfig::region2DisplayName {};
137 std::string LocaleConfig::currentDialectLocale = "";
138 std::string LocaleConfig::currentOverrideRegion = "";
139
140 set<std::string> LocaleConfig::validCaTag {
141 "buddhist",
142 "chinese",
143 "coptic",
144 "dangi",
145 "ethioaa",
146 "ethiopic",
147 "gregory",
148 "hebrew",
149 "indian",
150 "islamic",
151 "islamic-umalqura",
152 "islamic-tbla",
153 "islamic-civil",
154 "islamic-rgsa",
155 "iso8601",
156 "japanese",
157 "persian",
158 "roc",
159 "islamicc",
160 };
161 set<std::string> LocaleConfig::validCoTag {
162 "big5han",
163 "compat",
164 "dict",
165 "direct",
166 "ducet",
167 "eor",
168 "gb2312",
169 "phonebk",
170 "phonetic",
171 "pinyin",
172 "reformed",
173 "searchjl",
174 "stroke",
175 "trad",
176 "unihan",
177 "zhuyin",
178 };
179 set<std::string> LocaleConfig::validKnTag {
180 "true",
181 "false",
182 };
183 set<std::string> LocaleConfig::validKfTag {
184 "upper",
185 "lower",
186 "false",
187 };
188 set<std::string> LocaleConfig::validNuTag {
189 "adlm", "ahom", "arab", "arabext", "bali", "beng",
190 "bhks", "brah", "cakm", "cham", "deva", "diak",
191 "fullwide", "gong", "gonm", "gujr", "guru", "hanidec",
192 "hmng", "hmnp", "java", "kali", "khmr", "knda",
193 "lana", "lanatham", "laoo", "latn", "lepc", "limb",
194 "mathbold", "mathdbl", "mathmono", "mathsanb", "mathsans", "mlym",
195 "modi", "mong", "mroo", "mtei", "mymr", "mymrshan",
196 "mymrtlng", "newa", "nkoo", "olck", "orya", "osma",
197 "rohg", "saur", "segment", "shrd", "sind", "sinh",
198 "sora", "sund", "takr", "talu", "tamldec", "telu",
199 "thai", "tibt", "tirh", "vaii", "wara", "wcho",
200 };
201 set<std::string> LocaleConfig::validHcTag {
202 "h12",
203 "h23",
204 "h11",
205 "h24",
206 };
207
208 static unordered_map<string, string> g_languageMap = {
209 { "zh-Hans", "zh-Hans" },
210 { "zh-Hant", "zh-Hant" },
211 { "my-Qaag", "my-Qaag" },
212 { "es-Latn-419", "es-419" },
213 { "es-Latn-US", "es-419" },
214 { "az-Latn", "az-Latn" },
215 { "bs-Latn", "bs-Latn" },
216 { "en-Qaag", "en-Qaag" },
217 { "uz-Latn", "uz-Latn" },
218 { "sr-Latn", "sr-Latn" },
219 { "jv-Latn", "jv-Latn" },
220 { "pt-Latn-BR", "pt-BR" },
221 { "pa-Guru", "pa-Guru" },
222 { "mai-Deva", "mai-Deva" }
223 };
224
Adjust(const string & origin)225 string Adjust(const string &origin)
226 {
227 for (auto iter = g_languageMap.begin(); iter != g_languageMap.end(); ++iter) {
228 string key = iter->first;
229 if (!origin.compare(0, key.length(), key)) {
230 return iter->second;
231 }
232 }
233 return origin;
234 }
235
GetDisplayLanguageInner(const string & language,const string & displayLocaleTag,bool sentenceCase)236 string GetDisplayLanguageInner(const string &language, const string &displayLocaleTag, bool sentenceCase)
237 {
238 icu::UnicodeString unistr;
239 // 0 is the start position of language, 2 is the length of zh and fa
240 if (!language.compare(0, 2, "zh") || !language.compare(0, 2, "fa") || !language.compare(0, 2, "ro")) {
241 UErrorCode status = U_ZERO_ERROR;
242 icu::Locale displayLocale = icu::Locale::forLanguageTag(displayLocaleTag.c_str(), status);
243 if (status != U_ZERO_ERROR) {
244 return "";
245 }
246 icu::LocaleDisplayNames *dspNames = icu::LocaleDisplayNames::createInstance(displayLocale,
247 UDialectHandling::ULDN_DIALECT_NAMES);
248 icu::Locale tempLocale = icu::Locale::forLanguageTag(language.c_str(), status);
249 if (status != U_ZERO_ERROR) {
250 return "";
251 }
252 dspNames->localeDisplayName(tempLocale, unistr);
253 delete dspNames;
254 } else {
255 UErrorCode status = U_ZERO_ERROR;
256 icu::Locale displayLoc = icu::Locale::forLanguageTag(displayLocaleTag, status);
257 if (status != U_ZERO_ERROR) {
258 return "";
259 }
260 icu::Locale locale = icu::Locale::forLanguageTag(language, status);
261 if (status != U_ZERO_ERROR) {
262 return "";
263 }
264 locale.getDisplayName(displayLoc, unistr);
265 }
266 if (sentenceCase) {
267 UChar32 ch = ucase_toupper(unistr.char32At(0));
268 unistr.replace(0, 1, ch);
269 }
270 string out;
271 unistr.toUTF8String(out);
272 return out;
273 }
274
275 bool LocaleConfig::listsInitialized = LocaleConfig::InitializeLists();
276
GetSystemLanguage()277 string LocaleConfig::GetSystemLanguage()
278 {
279 std::string systemLanguage = ReadSystemParameter(LANGUAGE_KEY, CONFIG_LEN);
280 if (systemLanguage.empty()) {
281 systemLanguage = ReadSystemParameter(DEFAULT_LANGUAGE_KEY, CONFIG_LEN);
282 }
283 return systemLanguage;
284 }
285
GetSystemRegion()286 string LocaleConfig::GetSystemRegion()
287 {
288 UErrorCode status = U_ZERO_ERROR;
289 const char *country = nullptr;
290 std::string systemRegion = ReadSystemParameter(LOCALE_KEY, CONFIG_LEN);
291 if (!systemRegion.empty()) {
292 icu::Locale origin = icu::Locale::forLanguageTag(systemRegion, status);
293 if (U_SUCCESS(status)) {
294 country = origin.getCountry();
295 if (country != nullptr) {
296 return country;
297 }
298 }
299 }
300 systemRegion = ReadSystemParameter(DEFAULT_LOCALE_KEY, CONFIG_LEN);
301 if (!systemRegion.empty()) {
302 status = U_ZERO_ERROR;
303 icu::Locale origin = icu::Locale::forLanguageTag(systemRegion, status);
304 if (U_SUCCESS(status)) {
305 country = origin.getCountry();
306 if (country != nullptr) {
307 return country;
308 }
309 }
310 }
311 return "";
312 }
313
GetSystemLocale()314 string LocaleConfig::GetSystemLocale()
315 {
316 std::string systemLocale = ReadSystemParameter(LOCALE_KEY, CONFIG_LEN);
317 if (systemLocale.empty()) {
318 systemLocale = ReadSystemParameter(DEFAULT_LOCALE_KEY, CONFIG_LEN);
319 }
320 return systemLocale;
321 }
322
CheckPermission()323 bool LocaleConfig::CheckPermission()
324 {
325 uint64_t tokenId = IPCSkeleton::GetCallingFullTokenID();
326 bool isSystemApp = OHOS::Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(tokenId);
327 if (!isSystemApp) {
328 HiLog::Info(LABEL,
329 "LocaleConfig::CheckPermission: Get permission failed, because current app is not system app");
330 return false;
331 }
332 Security::AccessToken::AccessTokenID callerToken = IPCSkeleton::GetCallingTokenID();
333 int result = Security::AccessToken::PermissionState::PERMISSION_GRANTED;
334 if (Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(callerToken) ==
335 Security::AccessToken::ATokenTypeEnum::TOKEN_HAP) {
336 result = Security::AccessToken::AccessTokenKit::VerifyAccessToken(callerToken,
337 "ohos.permission.UPDATE_CONFIGURATION");
338 } else {
339 HiLog::Info(LABEL, "Invlid tokenID");
340 return false;
341 }
342 if (result != Security::AccessToken::PermissionState::PERMISSION_GRANTED) {
343 HiLog::Info(LABEL, "Verify permission failed");
344 return false;
345 }
346 return true;
347 }
348
SetSystemLanguage(const string & language)349 bool LocaleConfig::SetSystemLanguage(const string &language)
350 {
351 if (!CheckPermission()) {
352 return false;
353 }
354 if (!IsValidTag(language)) {
355 return false;
356 }
357 std::string oldLanguage = GetSystemLanguage();
358 if (SetParameter(LANGUAGE_KEY, language.data()) == 0) {
359 bool isUpdateSuccess = UpdateSystemLocale(language);
360 if (isUpdateSuccess) {
361 #ifdef SUPPORT_GRAPHICS
362 auto appMgrClient = std::make_unique<AppExecFwk::AppMgrClient>();
363 AppExecFwk::Configuration configuration;
364 configuration.AddItem(AAFwk::GlobalConfigurationKey::SYSTEM_LANGUAGE, language);
365 appMgrClient->UpdateConfiguration(configuration);
366
367 OHOS::AAFwk::Want localeChangeWant;
368 localeChangeWant.SetAction(OHOS::EventFwk::CommonEventSupport::COMMON_EVENT_LOCALE_CHANGED);
369 OHOS::EventFwk::CommonEventData event(localeChangeWant);
370 if (!OHOS::EventFwk::CommonEventManager::PublishCommonEvent(event)) {
371 HiLog::Info(LABEL, "Failed to Publish event %{public}s", localeChangeWant.GetAction().c_str());
372 return false;
373 }
374 #endif
375 return true;
376 } else {
377 SetParameter(LANGUAGE_KEY, oldLanguage.data());
378 return false;
379 }
380 }
381 return false;
382 }
383
SetSystemRegion(const string & region)384 bool LocaleConfig::SetSystemRegion(const string ®ion)
385 {
386 if (!CheckPermission()) {
387 return false;
388 }
389 if (!IsValidRegion(region)) {
390 return false;
391 }
392 char value[CONFIG_LEN];
393 int code = GetParameter(LOCALE_KEY, "", value, CONFIG_LEN);
394 string newLocale;
395 if (code > 0) {
396 string tag(value, code);
397 newLocale = GetRegionChangeLocale(tag, region);
398 if (newLocale == "") {
399 return false;
400 }
401 } else {
402 icu::Locale temp("", region.c_str());
403 UErrorCode status = U_ZERO_ERROR;
404 temp.addLikelySubtags(status);
405 if (status != U_ZERO_ERROR) {
406 return false;
407 }
408 newLocale = temp.toLanguageTag<string>(status);
409 if (status != U_ZERO_ERROR) {
410 return false;
411 }
412 }
413 return SetParameter(LOCALE_KEY, newLocale.data()) == 0;
414 }
415
SetSystemLocale(const string & locale)416 bool LocaleConfig::SetSystemLocale(const string &locale)
417 {
418 if (!CheckPermission()) {
419 return false;
420 }
421 if (!IsValidTag(locale)) {
422 return false;
423 }
424 return SetParameter(LOCALE_KEY, locale.data()) == 0;
425 }
426
IsValidLanguage(const string & language)427 bool LocaleConfig::IsValidLanguage(const string &language)
428 {
429 string::size_type size = language.size();
430 if ((size != LANGUAGE_LEN) && (size != LANGUAGE_LEN + 1)) {
431 return false;
432 }
433 for (size_t i = 0; i < size; ++i) {
434 if ((language[i] > 'z') || (language[i] < 'a')) {
435 return false;
436 }
437 }
438 return true;
439 }
440
IsValidRegion(const string & region)441 bool LocaleConfig::IsValidRegion(const string ®ion)
442 {
443 string::size_type size = region.size();
444 if (size != LocaleInfo::REGION_LEN) {
445 return false;
446 }
447 for (size_t i = 0; i < LocaleInfo::REGION_LEN; ++i) {
448 if ((region[i] > 'Z') || (region[i] < 'A')) {
449 return false;
450 }
451 }
452 return true;
453 }
454
IsValidTag(const string & tag)455 bool LocaleConfig::IsValidTag(const string &tag)
456 {
457 if (!tag.size()) {
458 return false;
459 }
460 vector<string> splits;
461 Split(tag, "-", splits);
462 if (!IsValidLanguage(splits[0])) {
463 return false;
464 }
465 return true;
466 }
467
Split(const string & src,const string & sep,vector<string> & dest)468 void LocaleConfig::Split(const string &src, const string &sep, vector<string> &dest)
469 {
470 string::size_type begin = 0;
471 string::size_type end = src.find(sep);
472 while (end != string::npos) {
473 dest.push_back(src.substr(begin, end - begin));
474 begin = end + sep.size();
475 end = src.find(sep, begin);
476 }
477 if (begin != src.size()) {
478 dest.push_back(src.substr(begin));
479 }
480 }
481
482 // language in white languages should have script.
GetSystemLanguages(vector<string> & ret)483 void LocaleConfig::GetSystemLanguages(vector<string> &ret)
484 {
485 std::copy(whiteLanguages.begin(), whiteLanguages.end(), std::back_inserter(ret));
486 }
487
GetSupportedLocales()488 const unordered_set<string>& LocaleConfig::GetSupportedLocales()
489 {
490 return supportedLocales;
491 }
492
GetSupportedRegions()493 const unordered_set<string>& LocaleConfig::GetSupportedRegions()
494 {
495 return supportedRegions;
496 }
497
GetSystemCountries(vector<string> & ret)498 void LocaleConfig::GetSystemCountries(vector<string> &ret)
499 {
500 std::copy(supportedRegions.begin(), supportedRegions.end(), std::back_inserter(ret));
501 }
502
IsSuggested(const string & language)503 bool LocaleConfig::IsSuggested(const string &language)
504 {
505 unordered_set<string> relatedLocales;
506 vector<string> simCountries;
507 GetCountriesFromSim(simCountries);
508 GetRelatedLocales(relatedLocales, simCountries);
509 for (auto iter = relatedLocales.begin(); iter != relatedLocales.end();) {
510 if (whiteLanguages.find(*iter) == whiteLanguages.end()) {
511 iter = relatedLocales.erase(iter);
512 } else {
513 ++iter;
514 }
515 }
516 string mainLanguage = GetMainLanguage(language);
517 return relatedLocales.find(mainLanguage) != relatedLocales.end();
518 }
519
IsSuggested(const std::string & language,const std::string & region)520 bool LocaleConfig::IsSuggested(const std::string &language, const std::string ®ion)
521 {
522 unordered_set<string> relatedLocales;
523 vector<string> countries { region };
524 GetRelatedLocales(relatedLocales, countries);
525 for (auto iter = relatedLocales.begin(); iter != relatedLocales.end();) {
526 if (whiteLanguages.find(*iter) == whiteLanguages.end()) {
527 iter = relatedLocales.erase(iter);
528 } else {
529 ++iter;
530 }
531 }
532 string mainLanguage = GetMainLanguage(language);
533 return relatedLocales.find(mainLanguage) != relatedLocales.end();
534 }
535
GetRelatedLocales(unordered_set<string> & relatedLocales,vector<string> countries)536 void LocaleConfig::GetRelatedLocales(unordered_set<string> &relatedLocales, vector<string> countries)
537 {
538 // remove unsupported countries
539 const unordered_set<string> ®ions = GetSupportedRegions();
540 for (auto iter = countries.begin(); iter != countries.end();) {
541 if (regions.find(*iter) == regions.end()) {
542 iter = countries.erase(iter);
543 } else {
544 ++iter;
545 }
546 }
547 const unordered_set<string> &locales = GetSupportedLocales();
548 for (string locale : locales) {
549 bool find = false;
550 for (string country : countries) {
551 if (locale.find(country) != string::npos) {
552 find = true;
553 break;
554 }
555 }
556 if (!find) {
557 continue;
558 }
559 string mainLanguage = GetMainLanguage(locale);
560 if (mainLanguage != "") {
561 relatedLocales.insert(mainLanguage);
562 }
563 }
564 }
565
GetCountriesFromSim(vector<string> & simCountries)566 void LocaleConfig::GetCountriesFromSim(vector<string> &simCountries)
567 {
568 simCountries.push_back(GetSystemRegion());
569 char value[CONFIG_LEN];
570 int code = GetParameter(SIM_COUNTRY_CODE_KEY, "", value, CONFIG_LEN);
571 if (code > 0) {
572 simCountries.push_back(value);
573 }
574 }
575
GetListFromFile(const char * path,const char * resourceName,unordered_set<string> & ret)576 void LocaleConfig::GetListFromFile(const char *path, const char *resourceName, unordered_set<string> &ret)
577 {
578 xmlKeepBlanksDefault(0);
579 if (!path) {
580 return;
581 }
582 xmlDocPtr doc = xmlParseFile(path);
583 if (!doc) {
584 return;
585 }
586 xmlNodePtr cur = xmlDocGetRootElement(doc);
587 if (!cur || xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>(resourceName))) {
588 xmlFreeDoc(doc);
589 return;
590 }
591 cur = cur->xmlChildrenNode;
592 xmlChar *content = nullptr;
593 while (cur != nullptr) {
594 content = xmlNodeGetContent(cur);
595 if (content != nullptr) {
596 ret.insert(reinterpret_cast<const char*>(content));
597 xmlFree(content);
598 cur = cur->next;
599 } else {
600 break;
601 }
602 }
603 xmlFreeDoc(doc);
604 }
605
ProcessForbiddenRegions(const unordered_set<string> & forbiddenRegions)606 void LocaleConfig::ProcessForbiddenRegions(const unordered_set<string> &forbiddenRegions)
607 {
608 for (auto it = forbiddenRegions.begin(); it != forbiddenRegions.end(); ++it) {
609 size_t pos = it->rfind("-");
610 std::string language = it->substr(0, pos);
611 std::string region = it->substr(pos + 1);
612 if (language.compare("*") == 0) {
613 blockedRegions.insert(region);
614 } else {
615 if (blockedLanguageRegions.find(language) == blockedLanguageRegions.end()) {
616 blockedLanguageRegions[language] = { region };
617 } else {
618 blockedLanguageRegions[language].insert(region);
619 }
620 }
621 }
622 }
623
Expunge(unordered_set<string> & src,const unordered_set<string> & another)624 void LocaleConfig::Expunge(unordered_set<string> &src, const unordered_set<string> &another)
625 {
626 for (auto iter = src.begin(); iter != src.end();) {
627 if (another.find(*iter) != another.end()) {
628 iter = src.erase(iter);
629 } else {
630 ++iter;
631 }
632 }
633 }
634
InitializeLists()635 bool LocaleConfig::InitializeLists()
636 {
637 SetHwIcuDirectory();
638 GetListFromFile(SUPPORTED_REGIONS_PATH, SUPPORTED_REGIONS_NAME, supportedRegions);
639 unordered_set<string> forbiddenRegions;
640 GetListFromFile(FORBIDDEN_REGIONS_PATH, FORBIDDEN_REGIONS_NAME, forbiddenRegions);
641 ProcessForbiddenRegions(forbiddenRegions);
642 Expunge(supportedRegions, blockedRegions);
643 GetListFromFile(WHITE_LANGUAGES_PATH, WHITE_LANGUAGES_NAME, whiteLanguages);
644 GetListFromFile(FORBIDDEN_LANGUAGES_PATH, FORBIDDEN_LANGUAGES_NAME, blockedLanguages);
645 Expunge(whiteLanguages, blockedLanguages);
646 GetListFromFile(SUPPORTED_LOCALES_PATH, SUPPORTED_LOCALES_NAME, supportedLocales);
647 GetListFromFile(SUPPORT_LOCALES_PATH, SUPPORT_LOCALES_NAME, supportLocales);
648 GetListFromFile(OVERRIDE_SUPPORTED_REGIONS_PATH, OVERRIDE_SUPPORTED_REGIONS_NAME, overrideSupportedRegions);
649 GetListFromFile(DIALECT_LANGS_PATH, DIALECT_LANGS_NAME, dialectLang);
650 return true;
651 }
652
GetRegionChangeLocale(const string & languageTag,const string & region)653 string LocaleConfig::GetRegionChangeLocale(const string &languageTag, const string ®ion)
654 {
655 UErrorCode status = U_ZERO_ERROR;
656 const icu::Locale origin = icu::Locale::forLanguageTag(languageTag, status);
657 if (status != U_ZERO_ERROR) {
658 return "";
659 }
660 icu::LocaleBuilder builder = icu::LocaleBuilder().setLanguage(origin.getLanguage()).
661 setScript(origin.getScript()).setRegion(region);
662 icu::Locale temp = builder.setExtension('u', "").build(status);
663 if (status != U_ZERO_ERROR) {
664 return "";
665 }
666 string ret = temp.toLanguageTag<string>(status);
667 return (status != U_ZERO_ERROR) ? "" : ret;
668 }
669
GetMainLanguage(const string & language)670 string LocaleConfig::GetMainLanguage(const string &language)
671 {
672 UErrorCode status = U_ZERO_ERROR;
673 icu::Locale origin = icu::Locale::forLanguageTag(language, status);
674 if (status != U_ZERO_ERROR) {
675 return "";
676 }
677 origin.addLikelySubtags(status);
678 if (status != U_ZERO_ERROR) {
679 return "";
680 }
681 icu::LocaleBuilder builder = icu::LocaleBuilder().setLanguage(origin.getLanguage()).
682 setScript(origin.getScript()).setRegion(origin.getCountry());
683 icu::Locale temp = builder.setExtension('u', "").build(status);
684 if (status != U_ZERO_ERROR) {
685 return "";
686 }
687 string fullLanguage = temp.toLanguageTag<string>(status);
688 if (status != U_ZERO_ERROR) {
689 return "";
690 }
691 if (dialectMap.find(fullLanguage) != dialectMap.end()) {
692 return dialectMap[fullLanguage];
693 }
694 builder.setRegion("");
695 temp = builder.build(status);
696 if (status != U_ZERO_ERROR) {
697 return "";
698 }
699 fullLanguage = temp.toLanguageTag<string>(status);
700 if (status != U_ZERO_ERROR) {
701 return "";
702 }
703 return fullLanguage;
704 }
705
GetDisplayLanguage(const string & language,const string & displayLocale,bool sentenceCase)706 string LocaleConfig::GetDisplayLanguage(const string &language, const string &displayLocale, bool sentenceCase)
707 {
708 string adjust = Adjust(language);
709 if (adjust == language) {
710 UErrorCode status = U_ZERO_ERROR;
711 icu::Locale displayLoc = icu::Locale::forLanguageTag(displayLocale, status);
712 if (status != U_ZERO_ERROR) {
713 return "";
714 }
715 icu::Locale locale = icu::Locale::forLanguageTag(language, status);
716 if (status != U_ZERO_ERROR) {
717 return "";
718 }
719 icu::UnicodeString unistr;
720 std::string lang(locale.getLanguage());
721 std::string result;
722 if (dialectLang.find(lang) != dialectLang.end()) {
723 result = GetDsiplayLanguageWithDialect(language, displayLocale);
724 } else {
725 locale.getDisplayLanguage(displayLoc, unistr);
726 unistr.toUTF8String(result);
727 }
728 if (sentenceCase) {
729 char ch = static_cast<char>(toupper(result[0]));
730 return result.replace(0, 1, 1, ch);
731 }
732 return result;
733 }
734 return GetDisplayLanguageInner(adjust, displayLocale, sentenceCase);
735 }
736
ComputeLocale(const std::string & displayLocale)737 std::string LocaleConfig::ComputeLocale(const std::string &displayLocale)
738 {
739 if (supportedDialectLocales.size() == 0) {
740 xmlKeepBlanksDefault(0);
741 xmlDocPtr doc = xmlParseFile(SUPPORT_LOCALES_PATH);
742 if (!doc) {
743 return DEFAULT_LOCALE;
744 }
745 xmlNodePtr cur = xmlDocGetRootElement(doc);
746 if (!cur || xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>(supportLocalesTag))) {
747 xmlFreeDoc(doc);
748 HiLog::Info(LABEL, "can not parse language supported locale file");
749 return DEFAULT_LOCALE;
750 }
751 cur = cur->xmlChildrenNode;
752 while (cur != nullptr) {
753 xmlChar *content = xmlNodeGetContent(cur);
754 if (content == nullptr) {
755 HiLog::Info(LABEL, "get xml node content failed");
756 break;
757 }
758 std::map<std::string, std::string> localeInfoConfigs = {};
759 LocaleInfo localeinfo(reinterpret_cast<const char*>(content), localeInfoConfigs);
760 std::string language = localeinfo.GetLanguage();
761 std::string script = localeinfo.GetScript();
762 std::string languageAndScript = (script.length() == 0) ? language : language + "-" + script;
763 LocaleInfo newLocaleInfo(languageAndScript, localeInfoConfigs);
764 std::string maximizeLocale = newLocaleInfo.Maximize();
765 supportedDialectLocales.insert(
766 std::make_pair<std::string, std::string>(maximizeLocale.c_str(),
767 reinterpret_cast<const char*>(content)));
768 xmlFree(content);
769 cur = cur->next;
770 }
771 }
772 std::map<std::string, std::string> configs = {};
773 LocaleInfo localeinfo(displayLocale, configs);
774 std::string language = localeinfo.GetLanguage();
775 std::string script = localeinfo.GetScript();
776 std::string languageAndScript = (script.length() == 0) ? language : language + "-" + script;
777 LocaleInfo newLocaleInfo(languageAndScript, configs);
778 std::string maximizeLocale = newLocaleInfo.Maximize();
779 if (supportedDialectLocales.find(maximizeLocale) != supportedDialectLocales.end()) {
780 return supportedDialectLocales.at(maximizeLocale);
781 }
782 return DEFAULT_LOCALE;
783 }
784
ReadLangData(const char * langDataPath)785 void LocaleConfig::ReadLangData(const char *langDataPath)
786 {
787 xmlKeepBlanksDefault(0);
788 if (langDataPath == nullptr) {
789 return;
790 }
791 xmlDocPtr doc = xmlParseFile(langDataPath);
792 if (!doc) {
793 HiLog::Info(LABEL, "can not open language data file");
794 return;
795 }
796 xmlNodePtr cur = xmlDocGetRootElement(doc);
797 if (!cur || xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>(rootTag))) {
798 xmlFreeDoc(doc);
799 HiLog::Info(LABEL, "parse language data file failed");
800 return;
801 }
802 cur = cur->xmlChildrenNode;
803 while (cur != nullptr && !xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>(secondRootTag))) {
804 xmlChar *langContents[ELEMENT_NUM] = { 0 }; // 2 represent langid, displayname;
805 xmlNodePtr langValue = cur->xmlChildrenNode;
806 for (size_t i = 0; i < ELEMENT_NUM; i++) {
807 if (langValue != nullptr) {
808 langContents[i] = xmlNodeGetContent(langValue);
809 langValue = langValue->next;
810 } else {
811 break;
812 }
813 }
814 // 0 represents langid index, 1 represents displayname index
815 locale2DisplayName.insert(
816 std::make_pair<std::string, std::string>(reinterpret_cast<const char *>(langContents[0]),
817 reinterpret_cast<const char *>(langContents[1])));
818 for (size_t i = 0; i < ELEMENT_NUM; i++) {
819 if (langContents[i] != nullptr) {
820 xmlFree(langContents[i]);
821 }
822 }
823 cur = cur->next;
824 }
825 xmlFreeDoc(doc);
826 }
827
ReadRegionData(const char * regionDataPath)828 void LocaleConfig::ReadRegionData(const char *regionDataPath)
829 {
830 xmlKeepBlanksDefault(0);
831 if (regionDataPath == nullptr) {
832 return;
833 }
834 xmlDocPtr doc = xmlParseFile(regionDataPath);
835 if (!doc) {
836 HiLog::Info(LABEL, "can not open region data file");
837 return;
838 }
839 xmlNodePtr cur = xmlDocGetRootElement(doc);
840 if (cur) {
841 HiLog::Info(LABEL, "cur pointer is true");
842 }
843 if (!cur || xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>(rootRegion))) {
844 xmlFreeDoc(doc);
845 HiLog::Info(LABEL, "parse region data file failed");
846 return;
847 }
848 cur = cur->xmlChildrenNode;
849 while (cur != nullptr && !xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>(secondRootRegion))) {
850 xmlChar *regionContents[ELEMENT_NUM] = { 0 };
851 xmlNodePtr regionValue = cur->xmlChildrenNode;
852 for (size_t i = 0; i < ELEMENT_NUM; i++) {
853 if (regionValue != nullptr) {
854 regionContents[i] = xmlNodeGetContent(regionValue);
855 regionValue = regionValue->next;
856 } else {
857 break;
858 }
859 }
860 // 0 represents langid index, 1 represents displayname index
861 region2DisplayName.insert(
862 std::make_pair<std::string, std::string>(reinterpret_cast<const char *>(regionContents[0]),
863 reinterpret_cast<const char *>(regionContents[1])));
864 for (size_t i = 0; i < ELEMENT_NUM; i++) {
865 if (regionContents[i] != nullptr) {
866 xmlFree(regionContents[i]);
867 }
868 }
869 cur = cur->next;
870 }
871 xmlFreeDoc(doc);
872 }
873
GetDsiplayLanguageWithDialect(const std::string & localeStr,const std::string & displayLocale)874 string LocaleConfig::GetDsiplayLanguageWithDialect(const std::string &localeStr, const std::string &displayLocale)
875 {
876 std::string finalLocale = ComputeLocale(displayLocale);
877 if (finalLocale.compare(currentDialectLocale) != 0) {
878 std::string xmlPath = LANG_PATH + finalLocale + ".xml";
879 locale2DisplayName.clear();
880 ReadLangData(xmlPath.c_str());
881 currentDialectLocale = finalLocale;
882 }
883 if (locale2DisplayName.find(localeStr) != locale2DisplayName.end()) {
884 return locale2DisplayName.at(localeStr);
885 }
886 std::map<std::string, std::string> configs = {};
887 LocaleInfo locale(localeStr, configs);
888 std::string language = locale.GetLanguage();
889 std::string scripts = locale.GetScript();
890 std::string region = locale.GetRegion();
891 if (scripts.length() != 0) {
892 std::string languageAndScripts = language + "-" + scripts;
893 if (locale2DisplayName.find(languageAndScripts) != locale2DisplayName.end()) {
894 return locale2DisplayName.at(languageAndScripts);
895 }
896 }
897 if (region.length() != 0) {
898 std::string languageAndRegion = language + "-" + region;
899 if (locale2DisplayName.find(languageAndRegion) != locale2DisplayName.end()) {
900 return locale2DisplayName.at(languageAndRegion);
901 }
902 }
903 if (locale2DisplayName.find(language) != locale2DisplayName.end()) {
904 return locale2DisplayName.at(language);
905 }
906 return "";
907 }
908
GetDisplayOverrideRegion(const std::string & region,const std::string & displayLocale)909 string LocaleConfig::GetDisplayOverrideRegion(const std::string ®ion, const std::string &displayLocale)
910 {
911 UErrorCode status = U_ZERO_ERROR;
912 icu::Locale originLocale;
913 icu::UnicodeString displayRegion;
914 if (displayLocale.compare(currentOverrideRegion) != 0) {
915 std::string xmlPath = REGION_PATH + displayLocale + ".xml";
916 region2DisplayName.clear();
917 ReadRegionData(xmlPath.c_str());
918 currentOverrideRegion = displayLocale;
919 }
920 if (region2DisplayName.find(region) != region2DisplayName.end()) {
921 return region2DisplayName.at(region);
922 } else {
923 icu::Locale locale = icu::Locale::forLanguageTag(displayLocale, status);
924 if (status != U_ZERO_ERROR) {
925 return "";
926 }
927 if (IsValidRegion(region)) {
928 icu::LocaleBuilder builder = icu::LocaleBuilder().setRegion(region);
929 originLocale = builder.build(status);
930 } else {
931 originLocale = icu::Locale::forLanguageTag(region, status);
932 }
933 originLocale.getDisplayCountry(locale, displayRegion);
934 std::string result;
935 displayRegion.toUTF8String(result);
936 return result;
937 }
938 }
939
GetDisplayRegion(const string & region,const string & displayLocale,bool sentenceCase)940 string LocaleConfig::GetDisplayRegion(const string ®ion, const string &displayLocale, bool sentenceCase)
941 {
942 UErrorCode status = U_ZERO_ERROR;
943 icu::Locale originLocale;
944 if (IsValidRegion(region)) {
945 icu::LocaleBuilder builder = icu::LocaleBuilder().setRegion(region);
946 originLocale = builder.build(status);
947 } else {
948 originLocale = icu::Locale::forLanguageTag(region, status);
949 }
950 std::string country(originLocale.getCountry());
951 if (country.length() == 0) {
952 return "";
953 }
954 if (status != U_ZERO_ERROR) {
955 return "";
956 }
957 icu::Locale locale = icu::Locale::forLanguageTag(displayLocale, status);
958 if (status != U_ZERO_ERROR) {
959 return "";
960 }
961 icu::UnicodeString unistr;
962 icu::UnicodeString displayRegion;
963 std::string result;
964 if (overrideSupportedRegions.find(displayLocale) != overrideSupportedRegions.end()) {
965 result = GetDisplayOverrideRegion(region, displayLocale);
966 } else {
967 originLocale.getDisplayCountry(locale, displayRegion);
968 displayRegion.toUTF8String(result);
969 }
970 if (sentenceCase) {
971 char ch = static_cast<char>(toupper(result[0]));
972 return result.replace(0, 1, 1, ch);
973 }
974 return result;
975 }
976
IsRTL(const string & locale)977 bool LocaleConfig::IsRTL(const string &locale)
978 {
979 icu::Locale curLocale(locale.c_str());
980 return curLocale.isRightToLeft();
981 }
982
parseExtension(const std::string & extension,std::map<std::string,std::string> & map)983 void parseExtension(const std::string &extension, std::map<std::string, std::string> &map)
984 {
985 std::string pattern = "-..-";
986 std::regex express(pattern);
987
988 std::regex_token_iterator<std::string::const_iterator> begin1(extension.cbegin(), extension.cend(), express);
989 std::regex_token_iterator<std::string::const_iterator> begin2(extension.cbegin(), extension.cend(), express, -1);
990 begin2++;
991 for (; begin1 != std::sregex_token_iterator() && begin2 != std::sregex_token_iterator(); begin1++, begin2++) {
992 map.insert(std::pair<std::string, std::string>(begin1->str(), begin2->str()));
993 }
994 }
995
setExtension(std::string & extension,const std::string & tag,const std::set<string> & validValue,const std::map<std::string,std::string> & extensionMap,const std::map<std::string,std::string> & defaultExtensionMap)996 void setExtension(std::string &extension, const std::string &tag, const std::set<string> &validValue,
997 const std::map<std::string, std::string> &extensionMap,
998 const std::map<std::string, std::string> &defaultExtensionMap)
999 {
1000 std::string value;
1001 auto it = extensionMap.find(tag);
1002 if (it != extensionMap.end()) {
1003 value = it->second;
1004 if (validValue.find(value) == validValue.end()) {
1005 return;
1006 } else {
1007 extension += tag;
1008 extension += value;
1009 }
1010 } else {
1011 it = defaultExtensionMap.find(tag);
1012 if (it != defaultExtensionMap.end()) {
1013 value = it->second;
1014 if (validValue.find(value) == validValue.end()) {
1015 return;
1016 } else {
1017 extension += tag;
1018 extension += value;
1019 }
1020 }
1021 }
1022 }
1023
setOtherExtension(std::string & extension,std::map<std::string,std::string> & extensionMap,std::map<std::string,std::string> & defaultExtensionMap)1024 void setOtherExtension(std::string &extension, std::map<std::string, std::string> &extensionMap,
1025 std::map<std::string, std::string> &defaultExtensionMap)
1026 {
1027 std::set<std::string> tags;
1028 tags.insert("-ca-");
1029 tags.insert("-co-");
1030 tags.insert("-kn-");
1031 tags.insert("-kf-");
1032 tags.insert("-nu-");
1033 tags.insert("-hc-");
1034
1035 for (auto it = tags.begin(); it != tags.end(); it++) {
1036 extensionMap.erase(*it);
1037 defaultExtensionMap.erase(*it);
1038 }
1039
1040 for (auto it = defaultExtensionMap.begin(); it != defaultExtensionMap.end(); it++) {
1041 extensionMap.insert(std::pair<std::string, std::string>(it->first, it->second));
1042 }
1043
1044 for (auto it = extensionMap.begin(); it != extensionMap.end(); it++) {
1045 extension += it->first;
1046 extension += it->second;
1047 }
1048 }
1049
GetValidLocale(const std::string & localeTag)1050 std::string LocaleConfig::GetValidLocale(const std::string &localeTag)
1051 {
1052 std::string baseLocale = "";
1053 std::string extension = "";
1054 std::size_t found = localeTag.find("-u-");
1055 baseLocale = localeTag.substr(0, found);
1056 if (found != std::string::npos) {
1057 extension = localeTag.substr(found);
1058 }
1059 std::map<std::string, std::string> extensionMap;
1060 if (extension != "") {
1061 parseExtension(extension, extensionMap);
1062 }
1063
1064 std::string systemLocaleTag = GetSystemLocale();
1065 std::string defaultExtension = "";
1066 found = systemLocaleTag.find("-u-");
1067 if (found != std::string::npos) {
1068 defaultExtension = systemLocaleTag.substr(found);
1069 }
1070 std::map<std::string, std::string> defaultExtensionMap;
1071 if (defaultExtension != "") {
1072 parseExtension(defaultExtension, defaultExtensionMap);
1073 }
1074
1075 std::string ext = "";
1076 setExtension(ext, "-ca-", validCaTag, extensionMap, defaultExtensionMap);
1077 setExtension(ext, "-co-", validCoTag, extensionMap, defaultExtensionMap);
1078 setExtension(ext, "-kn-", validKnTag, extensionMap, defaultExtensionMap);
1079 setExtension(ext, "-kf-", validKfTag, extensionMap, defaultExtensionMap);
1080 setExtension(ext, "-nu-", validNuTag, extensionMap, defaultExtensionMap);
1081 setExtension(ext, "-hc-", validHcTag, extensionMap, defaultExtensionMap);
1082
1083 std::string otherExt = "";
1084 setOtherExtension(otherExt, extensionMap, defaultExtensionMap);
1085 if (ext != "" || otherExt != "") {
1086 return baseLocale + "-u" + ext + otherExt;
1087 } else {
1088 return baseLocale;
1089 }
1090 }
1091
Is24HourClock()1092 bool LocaleConfig::Is24HourClock()
1093 {
1094 std::string is24Hour = ReadSystemParameter(HOUR_KEY, CONFIG_LEN);
1095 if (is24Hour.empty()) {
1096 return false;
1097 }
1098 if (is24Hour.compare("true") == 0) {
1099 return true;
1100 }
1101 return false;
1102 }
1103
Set24HourClock(bool option)1104 bool LocaleConfig::Set24HourClock(bool option)
1105 {
1106 if (!CheckPermission()) {
1107 return false;
1108 }
1109 std::string optionStr = "";
1110 if (option) {
1111 optionStr = "true";
1112 } else {
1113 optionStr = "false";
1114 }
1115 if (SetParameter(HOUR_KEY, optionStr.data()) == 0) {
1116 #ifdef SUPPORT_GRAPHICS
1117 auto appMgrClient = std::make_unique<AppExecFwk::AppMgrClient>();
1118 AppExecFwk::Configuration configuration;
1119 configuration.AddItem(AAFwk::GlobalConfigurationKey::SYSTEM_HOUR, optionStr);
1120 appMgrClient->UpdateConfiguration(configuration);
1121
1122 OHOS::AAFwk::Want timeChangeWant;
1123 timeChangeWant.SetAction(OHOS::EventFwk::CommonEventSupport::COMMON_EVENT_TIME_CHANGED);
1124 OHOS::EventFwk::CommonEventData event(timeChangeWant);
1125 if (!OHOS::EventFwk::CommonEventManager::PublishCommonEvent(event)) {
1126 HiLog::Info(LABEL, "Failed to Publish event %{public}s", timeChangeWant.GetAction().c_str());
1127 return false;
1128 }
1129 #endif
1130 return true;
1131 }
1132 return false;
1133 }
1134
SetUsingLocalDigit(bool flag)1135 bool LocaleConfig::SetUsingLocalDigit(bool flag)
1136 {
1137 if (!CheckPermission()) {
1138 return false;
1139 }
1140 std::string locale = GetSystemLocale();
1141 LocaleInfo localeInfo(locale);
1142 std::string language = localeInfo.GetLanguage();
1143 if (localDigitMap.find(language) == localDigitMap.end()) {
1144 return false;
1145 }
1146 std::string numberSystem = "-nu-" + localDigitMap.at(language);
1147 if (flag) {
1148 if (locale.find("-u-") == std::string::npos) {
1149 locale += "-u" + numberSystem;
1150 } else if (locale.find("-nu-") == std::string::npos) {
1151 locale += numberSystem;
1152 } else {
1153 std::string oldNumberSystem = "-nu-" + localeInfo.GetNumberingSystem();
1154 locale.replace(locale.find("-nu-"), oldNumberSystem.length(), numberSystem);
1155 }
1156 } else {
1157 size_t pos = locale.find(numberSystem);
1158 if (pos != std::string::npos) {
1159 locale.replace(pos, numberSystem.length(), "");
1160 }
1161 // 2 is string -u length
1162 if (locale.find("-u") == (locale.length() - 2)) {
1163 // 2 is string -u length
1164 locale.resize(locale.length() - 2);
1165 }
1166 }
1167 if (!SetSystemLocale(locale)) {
1168 return false;
1169 }
1170 return true;
1171 }
1172
GetUsingLocalDigit()1173 bool LocaleConfig::GetUsingLocalDigit()
1174 {
1175 std::string locale = GetSystemLocale();
1176 LocaleInfo localeInfo(locale);
1177 std::string language = localeInfo.GetLanguage();
1178 if (localDigitMap.find(language) == localDigitMap.end()) {
1179 return false;
1180 }
1181 std::string localNumberSystem = localDigitMap.at(language);
1182 if (localNumberSystem.compare(localeInfo.GetNumberingSystem()) != 0) {
1183 return false;
1184 }
1185 return true;
1186 }
1187
UpdateSystemLocale(const std::string & language)1188 bool LocaleConfig::UpdateSystemLocale(const std::string &language)
1189 {
1190 UErrorCode status = U_ZERO_ERROR;
1191 icu::Locale languageLocale = icu::Locale::forLanguageTag(language.c_str(), status);
1192 if (U_FAILURE(status)) {
1193 return false;
1194 }
1195 std::string lang = languageLocale.getLanguage();
1196 std::string script = languageLocale.getScript();
1197
1198 std::string systemLocaleTag = GetSystemLocale();
1199 icu::Locale systemLocale = icu::Locale::forLanguageTag(systemLocaleTag.c_str(), status);
1200 if (U_FAILURE(status)) {
1201 return false;
1202 }
1203 std::string region = systemLocale.getCountry();
1204
1205 std::string extendParam;
1206 size_t pos = systemLocaleTag.find("-u-");
1207 if (pos < systemLocaleTag.length()) {
1208 extendParam = systemLocaleTag.substr(pos);
1209 }
1210
1211 std::string finalLocaleTag = lang;
1212 std::string splitor = "-";
1213 if (script.length() > 0) {
1214 finalLocaleTag += splitor + script;
1215 }
1216 if (region.length() > 0) {
1217 finalLocaleTag += splitor + region;
1218 }
1219 if (extendParam.length() > 0) {
1220 finalLocaleTag += extendParam;
1221 }
1222 return SetSystemLocale(finalLocaleTag);
1223 }
1224
GetBlockedLanguages()1225 std::unordered_set<std::string> LocaleConfig::GetBlockedLanguages()
1226 {
1227 return blockedLanguages;
1228 }
1229
GetBlockedRegions()1230 std::unordered_set<std::string> LocaleConfig::GetBlockedRegions()
1231 {
1232 return blockedRegions;
1233 }
1234
GetLanguageBlockedRegions()1235 std::unordered_set<std::string> LocaleConfig::GetLanguageBlockedRegions()
1236 {
1237 std::string systemLanguage = LocaleConfig::GetSystemLanguage();
1238 if (blockedLanguageRegions.find(systemLanguage) != blockedLanguageRegions.end()) {
1239 return blockedLanguageRegions[systemLanguage];
1240 }
1241 std::unordered_set<std::string> emptyResult;
1242 return emptyResult;
1243 }
1244 } // namespace I18n
1245 } // namespace Global
1246 } // namespace OHOS
1247