• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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         if (dspNames != nullptr) {
253             dspNames->localeDisplayName(tempLocale, unistr);
254             delete dspNames;
255         }
256     } else {
257         UErrorCode status = U_ZERO_ERROR;
258         icu::Locale displayLoc = icu::Locale::forLanguageTag(displayLocaleTag, status);
259         if (status != U_ZERO_ERROR) {
260             return "";
261         }
262         icu::Locale locale = icu::Locale::forLanguageTag(language, status);
263         if (status != U_ZERO_ERROR) {
264             return "";
265         }
266         locale.getDisplayName(displayLoc, unistr);
267     }
268     if (sentenceCase) {
269         UChar32 ch = ucase_toupper(unistr.char32At(0));
270         unistr.replace(0, 1, ch);
271     }
272     string out;
273     unistr.toUTF8String(out);
274     return out;
275 }
276 
277 bool LocaleConfig::listsInitialized = LocaleConfig::InitializeLists();
278 
GetSystemLanguage()279 string LocaleConfig::GetSystemLanguage()
280 {
281     std::string systemLanguage = ReadSystemParameter(LANGUAGE_KEY, CONFIG_LEN);
282     if (systemLanguage.empty()) {
283         systemLanguage = ReadSystemParameter(DEFAULT_LANGUAGE_KEY, CONFIG_LEN);
284     }
285     return systemLanguage;
286 }
287 
GetSystemRegion()288 string LocaleConfig::GetSystemRegion()
289 {
290     UErrorCode status = U_ZERO_ERROR;
291     const char *country = nullptr;
292     std::string systemRegion = ReadSystemParameter(LOCALE_KEY, CONFIG_LEN);
293     if (!systemRegion.empty()) {
294         icu::Locale origin = icu::Locale::forLanguageTag(systemRegion, status);
295         if (U_SUCCESS(status)) {
296             country = origin.getCountry();
297             if (country != nullptr) {
298                 return country;
299             }
300         }
301     }
302     systemRegion = ReadSystemParameter(DEFAULT_LOCALE_KEY, CONFIG_LEN);
303     if (!systemRegion.empty()) {
304         status = U_ZERO_ERROR;
305         icu::Locale origin = icu::Locale::forLanguageTag(systemRegion, status);
306         if (U_SUCCESS(status)) {
307             country = origin.getCountry();
308             if (country != nullptr) {
309                 return country;
310             }
311         }
312     }
313     return "";
314 }
315 
GetSystemLocale()316 string LocaleConfig::GetSystemLocale()
317 {
318     std::string systemLocale = ReadSystemParameter(LOCALE_KEY, CONFIG_LEN);
319     if (systemLocale.empty()) {
320         systemLocale = ReadSystemParameter(DEFAULT_LOCALE_KEY, CONFIG_LEN);
321     }
322     return systemLocale;
323 }
324 
CheckPermission()325 bool LocaleConfig::CheckPermission()
326 {
327     uint64_t tokenId = IPCSkeleton::GetCallingFullTokenID();
328     bool isSystemApp = OHOS::Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(tokenId);
329     if (!isSystemApp) {
330         HiLog::Info(LABEL,
331             "LocaleConfig::CheckPermission: Get permission failed, because current app is not system app");
332         return false;
333     }
334     Security::AccessToken::AccessTokenID callerToken = IPCSkeleton::GetCallingTokenID();
335     int result = Security::AccessToken::PermissionState::PERMISSION_GRANTED;
336     if (Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(callerToken) ==
337         Security::AccessToken::ATokenTypeEnum::TOKEN_HAP) {
338         result = Security::AccessToken::AccessTokenKit::VerifyAccessToken(callerToken,
339                                                                           "ohos.permission.UPDATE_CONFIGURATION");
340     } else {
341         HiLog::Info(LABEL, "Invlid tokenID");
342         return false;
343     }
344     if (result != Security::AccessToken::PermissionState::PERMISSION_GRANTED) {
345         HiLog::Info(LABEL, "Verify permission failed");
346         return false;
347     }
348     return true;
349 }
350 
SetSystemLanguage(const string & language)351 bool LocaleConfig::SetSystemLanguage(const string &language)
352 {
353     if (!CheckPermission()) {
354         return false;
355     }
356     if (!IsValidTag(language)) {
357         return false;
358     }
359     std::string oldLanguage = GetSystemLanguage();
360     if (SetParameter(LANGUAGE_KEY, language.data()) == 0) {
361         bool isUpdateSuccess = UpdateSystemLocale(language);
362         if (isUpdateSuccess) {
363 #ifdef SUPPORT_GRAPHICS
364         auto appMgrClient = std::make_unique<AppExecFwk::AppMgrClient>();
365         AppExecFwk::Configuration configuration;
366         configuration.AddItem(AAFwk::GlobalConfigurationKey::SYSTEM_LANGUAGE, language);
367         appMgrClient->UpdateConfiguration(configuration);
368 
369         OHOS::AAFwk::Want localeChangeWant;
370         localeChangeWant.SetAction(OHOS::EventFwk::CommonEventSupport::COMMON_EVENT_LOCALE_CHANGED);
371         OHOS::EventFwk::CommonEventData event(localeChangeWant);
372         if (!OHOS::EventFwk::CommonEventManager::PublishCommonEvent(event)) {
373             HiLog::Info(LABEL, "Failed to Publish event %{public}s", localeChangeWant.GetAction().c_str());
374             return false;
375         }
376 #endif
377             return true;
378         } else {
379             SetParameter(LANGUAGE_KEY, oldLanguage.data());
380             return false;
381         }
382     }
383     return false;
384 }
385 
SetSystemRegion(const string & region)386 bool LocaleConfig::SetSystemRegion(const string &region)
387 {
388     if (!CheckPermission()) {
389         return false;
390     }
391     if (!IsValidRegion(region)) {
392         return false;
393     }
394     char value[CONFIG_LEN];
395     int code = GetParameter(LOCALE_KEY, "", value, CONFIG_LEN);
396     string newLocale;
397     if (code > 0) {
398         string tag(value, code);
399         newLocale = GetRegionChangeLocale(tag, region);
400         if (newLocale == "") {
401             return false;
402         }
403     } else {
404         icu::Locale temp("", region.c_str());
405         UErrorCode status = U_ZERO_ERROR;
406         temp.addLikelySubtags(status);
407         if (status != U_ZERO_ERROR) {
408             return false;
409         }
410         newLocale = temp.toLanguageTag<string>(status);
411         if (status != U_ZERO_ERROR) {
412             return false;
413         }
414     }
415     return SetParameter(LOCALE_KEY, newLocale.data()) == 0;
416 }
417 
SetSystemLocale(const string & locale)418 bool LocaleConfig::SetSystemLocale(const string &locale)
419 {
420     if (!CheckPermission()) {
421         return false;
422     }
423     if (!IsValidTag(locale)) {
424         return false;
425     }
426     return SetParameter(LOCALE_KEY, locale.data()) == 0;
427 }
428 
IsValidLanguage(const string & language)429 bool LocaleConfig::IsValidLanguage(const string &language)
430 {
431     string::size_type size = language.size();
432     if ((size != LANGUAGE_LEN) && (size != LANGUAGE_LEN + 1)) {
433         return false;
434     }
435     for (size_t i = 0; i < size; ++i) {
436         if ((language[i] > 'z') || (language[i] < 'a')) {
437             return false;
438         }
439     }
440     return true;
441 }
442 
IsValidRegion(const string & region)443 bool LocaleConfig::IsValidRegion(const string &region)
444 {
445     string::size_type size = region.size();
446     if (size != LocaleInfo::REGION_LEN) {
447         return false;
448     }
449     for (size_t i = 0; i < LocaleInfo::REGION_LEN; ++i) {
450         if ((region[i] > 'Z') || (region[i] < 'A')) {
451             return false;
452         }
453     }
454     return true;
455 }
456 
IsValidTag(const string & tag)457 bool LocaleConfig::IsValidTag(const string &tag)
458 {
459     if (!tag.size()) {
460         return false;
461     }
462     vector<string> splits;
463     Split(tag, "-", splits);
464     if (!IsValidLanguage(splits[0])) {
465         return false;
466     }
467     return true;
468 }
469 
Split(const string & src,const string & sep,vector<string> & dest)470 void LocaleConfig::Split(const string &src, const string &sep, vector<string> &dest)
471 {
472     string::size_type begin = 0;
473     string::size_type end = src.find(sep);
474     while (end != string::npos) {
475         dest.push_back(src.substr(begin, end - begin));
476         begin = end + sep.size();
477         end = src.find(sep, begin);
478     }
479     if (begin != src.size()) {
480         dest.push_back(src.substr(begin));
481     }
482 }
483 
484 // language in white languages should have script.
GetSystemLanguages(vector<string> & ret)485 void LocaleConfig::GetSystemLanguages(vector<string> &ret)
486 {
487     std::copy(whiteLanguages.begin(), whiteLanguages.end(), std::back_inserter(ret));
488 }
489 
GetSupportedLocales()490 const unordered_set<string>& LocaleConfig::GetSupportedLocales()
491 {
492     return supportedLocales;
493 }
494 
GetSupportedRegions()495 const unordered_set<string>& LocaleConfig::GetSupportedRegions()
496 {
497     return supportedRegions;
498 }
499 
GetSystemCountries(vector<string> & ret)500 void LocaleConfig::GetSystemCountries(vector<string> &ret)
501 {
502     std::copy(supportedRegions.begin(), supportedRegions.end(), std::back_inserter(ret));
503 }
504 
IsSuggested(const string & language)505 bool LocaleConfig::IsSuggested(const string &language)
506 {
507     unordered_set<string> relatedLocales;
508     vector<string> simCountries;
509     GetCountriesFromSim(simCountries);
510     GetRelatedLocales(relatedLocales, simCountries);
511     for (auto iter = relatedLocales.begin(); iter != relatedLocales.end();) {
512         if (whiteLanguages.find(*iter) == whiteLanguages.end()) {
513             iter = relatedLocales.erase(iter);
514         } else {
515             ++iter;
516         }
517     }
518     string mainLanguage = GetMainLanguage(language);
519     return relatedLocales.find(mainLanguage) != relatedLocales.end();
520 }
521 
IsSuggested(const std::string & language,const std::string & region)522 bool LocaleConfig::IsSuggested(const std::string &language, const std::string &region)
523 {
524     unordered_set<string> relatedLocales;
525     vector<string> countries { region };
526     GetRelatedLocales(relatedLocales, countries);
527     for (auto iter = relatedLocales.begin(); iter != relatedLocales.end();) {
528         if (whiteLanguages.find(*iter) == whiteLanguages.end()) {
529             iter = relatedLocales.erase(iter);
530         } else {
531             ++iter;
532         }
533     }
534     string mainLanguage = GetMainLanguage(language);
535     return relatedLocales.find(mainLanguage) != relatedLocales.end();
536 }
537 
GetRelatedLocales(unordered_set<string> & relatedLocales,vector<string> countries)538 void LocaleConfig::GetRelatedLocales(unordered_set<string> &relatedLocales, vector<string> countries)
539 {
540     // remove unsupported countries
541     const unordered_set<string> &regions = GetSupportedRegions();
542     for (auto iter = countries.begin(); iter != countries.end();) {
543         if (regions.find(*iter) == regions.end()) {
544             iter = countries.erase(iter);
545         } else {
546             ++iter;
547         }
548     }
549     const unordered_set<string> &locales = GetSupportedLocales();
550     for (string locale : locales) {
551         bool find = false;
552         for (string country : countries) {
553             if (locale.find(country) != string::npos) {
554                 find = true;
555                 break;
556             }
557         }
558         if (!find) {
559             continue;
560         }
561         string mainLanguage = GetMainLanguage(locale);
562         if (mainLanguage != "") {
563             relatedLocales.insert(mainLanguage);
564         }
565     }
566 }
567 
GetCountriesFromSim(vector<string> & simCountries)568 void LocaleConfig::GetCountriesFromSim(vector<string> &simCountries)
569 {
570     simCountries.push_back(GetSystemRegion());
571     char value[CONFIG_LEN];
572     int code = GetParameter(SIM_COUNTRY_CODE_KEY, "", value, CONFIG_LEN);
573     if (code > 0) {
574         simCountries.push_back(value);
575     }
576 }
577 
GetListFromFile(const char * path,const char * resourceName,unordered_set<string> & ret)578 void LocaleConfig::GetListFromFile(const char *path, const char *resourceName, unordered_set<string> &ret)
579 {
580     xmlKeepBlanksDefault(0);
581     if (!path) {
582         return;
583     }
584     xmlDocPtr doc = xmlParseFile(path);
585     if (!doc) {
586         return;
587     }
588     xmlNodePtr cur = xmlDocGetRootElement(doc);
589     if (!cur || xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>(resourceName))) {
590         xmlFreeDoc(doc);
591         return;
592     }
593     cur = cur->xmlChildrenNode;
594     xmlChar *content = nullptr;
595     while (cur != nullptr) {
596         content = xmlNodeGetContent(cur);
597         if (content != nullptr) {
598             ret.insert(reinterpret_cast<const char*>(content));
599             xmlFree(content);
600             cur = cur->next;
601         } else {
602             break;
603         }
604     }
605     xmlFreeDoc(doc);
606 }
607 
ProcessForbiddenRegions(const unordered_set<string> & forbiddenRegions)608 void LocaleConfig::ProcessForbiddenRegions(const unordered_set<string> &forbiddenRegions)
609 {
610     for (auto it = forbiddenRegions.begin(); it != forbiddenRegions.end(); ++it) {
611         size_t pos = it->rfind("-");
612         std::string language = it->substr(0, pos);
613         std::string region = it->substr(pos + 1);
614         if (language.compare("*") == 0) {
615             blockedRegions.insert(region);
616         } else {
617             if (blockedLanguageRegions.find(language) == blockedLanguageRegions.end()) {
618                 blockedLanguageRegions[language] = { region };
619             } else {
620                 blockedLanguageRegions[language].insert(region);
621             }
622         }
623     }
624 }
625 
Expunge(unordered_set<string> & src,const unordered_set<string> & another)626 void LocaleConfig::Expunge(unordered_set<string> &src, const unordered_set<string> &another)
627 {
628     for (auto iter = src.begin(); iter != src.end();) {
629         if (another.find(*iter) != another.end()) {
630             iter = src.erase(iter);
631         } else {
632             ++iter;
633         }
634     }
635 }
636 
InitializeLists()637 bool LocaleConfig::InitializeLists()
638 {
639     SetHwIcuDirectory();
640     GetListFromFile(SUPPORTED_REGIONS_PATH, SUPPORTED_REGIONS_NAME, supportedRegions);
641     unordered_set<string> forbiddenRegions;
642     GetListFromFile(FORBIDDEN_REGIONS_PATH, FORBIDDEN_REGIONS_NAME, forbiddenRegions);
643     ProcessForbiddenRegions(forbiddenRegions);
644     Expunge(supportedRegions, blockedRegions);
645     GetListFromFile(WHITE_LANGUAGES_PATH, WHITE_LANGUAGES_NAME, whiteLanguages);
646     GetListFromFile(FORBIDDEN_LANGUAGES_PATH, FORBIDDEN_LANGUAGES_NAME, blockedLanguages);
647     Expunge(whiteLanguages, blockedLanguages);
648     GetListFromFile(SUPPORTED_LOCALES_PATH, SUPPORTED_LOCALES_NAME, supportedLocales);
649     GetListFromFile(SUPPORT_LOCALES_PATH, SUPPORT_LOCALES_NAME, supportLocales);
650     GetListFromFile(OVERRIDE_SUPPORTED_REGIONS_PATH, OVERRIDE_SUPPORTED_REGIONS_NAME, overrideSupportedRegions);
651     GetListFromFile(DIALECT_LANGS_PATH, DIALECT_LANGS_NAME, dialectLang);
652     return true;
653 }
654 
GetRegionChangeLocale(const string & languageTag,const string & region)655 string LocaleConfig::GetRegionChangeLocale(const string &languageTag, const string &region)
656 {
657     UErrorCode status = U_ZERO_ERROR;
658     const icu::Locale origin = icu::Locale::forLanguageTag(languageTag, status);
659     if (status != U_ZERO_ERROR) {
660         return "";
661     }
662     icu::LocaleBuilder builder = icu::LocaleBuilder().setLanguage(origin.getLanguage()).
663         setScript(origin.getScript()).setRegion(region);
664     icu::Locale temp = builder.setExtension('u', "").build(status);
665     if (status != U_ZERO_ERROR) {
666         return "";
667     }
668     string ret = temp.toLanguageTag<string>(status);
669     return (status != U_ZERO_ERROR) ? "" : ret;
670 }
671 
GetMainLanguage(const string & language)672 string LocaleConfig::GetMainLanguage(const string &language)
673 {
674     UErrorCode status = U_ZERO_ERROR;
675     icu::Locale origin = icu::Locale::forLanguageTag(language, status);
676     if (status != U_ZERO_ERROR) {
677         return "";
678     }
679     origin.addLikelySubtags(status);
680     if (status != U_ZERO_ERROR) {
681         return "";
682     }
683     icu::LocaleBuilder builder = icu::LocaleBuilder().setLanguage(origin.getLanguage()).
684         setScript(origin.getScript()).setRegion(origin.getCountry());
685     icu::Locale temp = builder.setExtension('u', "").build(status);
686     if (status != U_ZERO_ERROR) {
687         return "";
688     }
689     string fullLanguage = temp.toLanguageTag<string>(status);
690     if (status != U_ZERO_ERROR) {
691         return "";
692     }
693     if (dialectMap.find(fullLanguage) != dialectMap.end()) {
694         return dialectMap[fullLanguage];
695     }
696     builder.setRegion("");
697     temp = builder.build(status);
698     if (status != U_ZERO_ERROR) {
699         return "";
700     }
701     fullLanguage = temp.toLanguageTag<string>(status);
702     if (status != U_ZERO_ERROR) {
703         return "";
704     }
705     return fullLanguage;
706 }
707 
GetDisplayLanguage(const string & language,const string & displayLocale,bool sentenceCase)708 string LocaleConfig::GetDisplayLanguage(const string &language, const string &displayLocale, bool sentenceCase)
709 {
710     string adjust = Adjust(language);
711     if (adjust == language) {
712         UErrorCode status = U_ZERO_ERROR;
713         icu::Locale displayLoc = icu::Locale::forLanguageTag(displayLocale, status);
714         if (status != U_ZERO_ERROR) {
715             return "";
716         }
717         icu::Locale locale = icu::Locale::forLanguageTag(language, status);
718         if (status != U_ZERO_ERROR) {
719             return "";
720         }
721         icu::UnicodeString unistr;
722         std::string lang(locale.getLanguage());
723         std::string result;
724         if (dialectLang.find(lang) != dialectLang.end()) {
725             result = GetDsiplayLanguageWithDialect(language, displayLocale);
726         } else {
727             locale.getDisplayLanguage(displayLoc, unistr);
728             unistr.toUTF8String(result);
729         }
730         if (sentenceCase) {
731             char ch = static_cast<char>(toupper(result[0]));
732             return result.replace(0, 1, 1, ch);
733         }
734         return result;
735     }
736     return GetDisplayLanguageInner(adjust, displayLocale, sentenceCase);
737 }
738 
ComputeLocale(const std::string & displayLocale)739 std::string LocaleConfig::ComputeLocale(const std::string &displayLocale)
740 {
741     if (supportedDialectLocales.size() == 0) {
742         xmlKeepBlanksDefault(0);
743         xmlDocPtr doc = xmlParseFile(SUPPORT_LOCALES_PATH);
744         if (!doc) {
745             return DEFAULT_LOCALE;
746         }
747         xmlNodePtr cur = xmlDocGetRootElement(doc);
748         if (!cur || xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>(supportLocalesTag))) {
749             xmlFreeDoc(doc);
750             HiLog::Info(LABEL, "can not parse language supported locale file");
751             return DEFAULT_LOCALE;
752         }
753         cur = cur->xmlChildrenNode;
754         while (cur != nullptr) {
755             xmlChar *content = xmlNodeGetContent(cur);
756             if (content == nullptr) {
757                 HiLog::Info(LABEL, "get xml node content failed");
758                 break;
759             }
760             std::map<std::string, std::string> localeInfoConfigs = {};
761             LocaleInfo localeinfo(reinterpret_cast<const char*>(content), localeInfoConfigs);
762             std::string language = localeinfo.GetLanguage();
763             std::string script = localeinfo.GetScript();
764             std::string languageAndScript = (script.length() == 0) ? language : language + "-" + script;
765             LocaleInfo newLocaleInfo(languageAndScript, localeInfoConfigs);
766             std::string maximizeLocale = newLocaleInfo.Maximize();
767             supportedDialectLocales.insert(
768                 std::make_pair<std::string, std::string>(maximizeLocale.c_str(),
769                                                          reinterpret_cast<const char*>(content)));
770             xmlFree(content);
771             cur = cur->next;
772         }
773     }
774     std::map<std::string, std::string> configs = {};
775     LocaleInfo localeinfo(displayLocale, configs);
776     std::string language = localeinfo.GetLanguage();
777     std::string script = localeinfo.GetScript();
778     std::string languageAndScript = (script.length() == 0) ? language : language + "-" + script;
779     LocaleInfo newLocaleInfo(languageAndScript, configs);
780     std::string maximizeLocale = newLocaleInfo.Maximize();
781     if (supportedDialectLocales.find(maximizeLocale) != supportedDialectLocales.end()) {
782         return supportedDialectLocales.at(maximizeLocale);
783     }
784     return DEFAULT_LOCALE;
785 }
786 
ReadLangData(const char * langDataPath)787 void LocaleConfig::ReadLangData(const char *langDataPath)
788 {
789     xmlKeepBlanksDefault(0);
790     if (langDataPath == nullptr) {
791         return;
792     }
793     xmlDocPtr doc = xmlParseFile(langDataPath);
794     if (!doc) {
795         HiLog::Info(LABEL, "can not open language data file");
796         return;
797     }
798     xmlNodePtr cur = xmlDocGetRootElement(doc);
799     if (!cur || xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>(rootTag))) {
800         xmlFreeDoc(doc);
801         HiLog::Info(LABEL, "parse language data file failed");
802         return;
803     }
804     cur = cur->xmlChildrenNode;
805     while (cur != nullptr && !xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>(secondRootTag))) {
806         xmlChar *langContents[ELEMENT_NUM] = { 0 }; // 2 represent langid, displayname;
807         xmlNodePtr langValue = cur->xmlChildrenNode;
808         for (size_t i = 0; i < ELEMENT_NUM; i++) {
809             if (langValue != nullptr) {
810                 langContents[i] = xmlNodeGetContent(langValue);
811                 langValue = langValue->next;
812             } else {
813                 break;
814             }
815         }
816         // 0 represents langid index, 1 represents displayname index
817         locale2DisplayName.insert(
818             std::make_pair<std::string, std::string>(reinterpret_cast<const char *>(langContents[0]),
819                                                      reinterpret_cast<const char *>(langContents[1])));
820         for (size_t i = 0; i < ELEMENT_NUM; i++) {
821             if (langContents[i] != nullptr) {
822                 xmlFree(langContents[i]);
823             }
824         }
825         cur = cur->next;
826     }
827     xmlFreeDoc(doc);
828 }
829 
ReadRegionData(const char * regionDataPath)830 void LocaleConfig::ReadRegionData(const char *regionDataPath)
831 {
832     xmlKeepBlanksDefault(0);
833     if (regionDataPath == nullptr) {
834         return;
835     }
836     xmlDocPtr doc = xmlParseFile(regionDataPath);
837     if (!doc) {
838         HiLog::Info(LABEL, "can not open region data file");
839         return;
840     }
841     xmlNodePtr cur = xmlDocGetRootElement(doc);
842     if (cur) {
843         HiLog::Info(LABEL, "cur pointer is true");
844     }
845     if (!cur || xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>(rootRegion))) {
846         xmlFreeDoc(doc);
847         HiLog::Info(LABEL, "parse region data file failed");
848         return;
849     }
850     cur = cur->xmlChildrenNode;
851     while (cur != nullptr && !xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>(secondRootRegion))) {
852         xmlChar *regionContents[ELEMENT_NUM] = { 0 };
853         xmlNodePtr regionValue = cur->xmlChildrenNode;
854         for (size_t i = 0; i < ELEMENT_NUM; i++) {
855             if (regionValue != nullptr) {
856                 regionContents[i] = xmlNodeGetContent(regionValue);
857                 regionValue = regionValue->next;
858             } else {
859                 break;
860             }
861         }
862         // 0 represents langid index, 1 represents displayname index
863         region2DisplayName.insert(
864             std::make_pair<std::string, std::string>(reinterpret_cast<const char *>(regionContents[0]),
865                                                      reinterpret_cast<const char *>(regionContents[1])));
866         for (size_t i = 0; i < ELEMENT_NUM; i++) {
867             if (regionContents[i] != nullptr) {
868                 xmlFree(regionContents[i]);
869             }
870         }
871         cur = cur->next;
872     }
873     xmlFreeDoc(doc);
874 }
875 
GetDsiplayLanguageWithDialect(const std::string & localeStr,const std::string & displayLocale)876 string LocaleConfig::GetDsiplayLanguageWithDialect(const std::string &localeStr, const std::string &displayLocale)
877 {
878     std::string finalLocale = ComputeLocale(displayLocale);
879     if (finalLocale.compare(currentDialectLocale) != 0) {
880         std::string xmlPath = LANG_PATH + finalLocale + ".xml";
881         locale2DisplayName.clear();
882         ReadLangData(xmlPath.c_str());
883         currentDialectLocale = finalLocale;
884     }
885     if (locale2DisplayName.find(localeStr) != locale2DisplayName.end()) {
886         return locale2DisplayName.at(localeStr);
887     }
888     std::map<std::string, std::string> configs = {};
889     LocaleInfo locale(localeStr, configs);
890     std::string language = locale.GetLanguage();
891     std::string scripts = locale.GetScript();
892     std::string region = locale.GetRegion();
893     if (scripts.length() != 0) {
894         std::string languageAndScripts = language + "-" + scripts;
895         if (locale2DisplayName.find(languageAndScripts) != locale2DisplayName.end()) {
896             return locale2DisplayName.at(languageAndScripts);
897         }
898     }
899     if (region.length() != 0) {
900         std::string languageAndRegion = language + "-" + region;
901         if (locale2DisplayName.find(languageAndRegion) != locale2DisplayName.end()) {
902             return locale2DisplayName.at(languageAndRegion);
903         }
904     }
905     if (locale2DisplayName.find(language) != locale2DisplayName.end()) {
906         return locale2DisplayName.at(language);
907     }
908     return "";
909 }
910 
GetDisplayOverrideRegion(const std::string & region,const std::string & displayLocale)911 string LocaleConfig::GetDisplayOverrideRegion(const std::string &region, const std::string &displayLocale)
912 {
913     UErrorCode status = U_ZERO_ERROR;
914     icu::Locale originLocale;
915     icu::UnicodeString displayRegion;
916     if (displayLocale.compare(currentOverrideRegion) != 0) {
917         std::string xmlPath = REGION_PATH + displayLocale + ".xml";
918         region2DisplayName.clear();
919         ReadRegionData(xmlPath.c_str());
920         currentOverrideRegion = displayLocale;
921     }
922     if (region2DisplayName.find(region) != region2DisplayName.end()) {
923         return region2DisplayName.at(region);
924     } else {
925         icu::Locale locale = icu::Locale::forLanguageTag(displayLocale, status);
926         if (status != U_ZERO_ERROR) {
927             return "";
928         }
929         if (IsValidRegion(region)) {
930             icu::LocaleBuilder builder = icu::LocaleBuilder().setRegion(region);
931             originLocale = builder.build(status);
932         } else {
933             originLocale = icu::Locale::forLanguageTag(region, status);
934         }
935         originLocale.getDisplayCountry(locale, displayRegion);
936         std::string result;
937         displayRegion.toUTF8String(result);
938         return result;
939     }
940 }
941 
GetDisplayRegion(const string & region,const string & displayLocale,bool sentenceCase)942 string LocaleConfig::GetDisplayRegion(const string &region, const string &displayLocale, bool sentenceCase)
943 {
944     UErrorCode status = U_ZERO_ERROR;
945     icu::Locale originLocale;
946     if (IsValidRegion(region)) {
947         icu::LocaleBuilder builder = icu::LocaleBuilder().setRegion(region);
948         originLocale = builder.build(status);
949     } else {
950         originLocale = icu::Locale::forLanguageTag(region, status);
951     }
952     std::string country(originLocale.getCountry());
953     if (country.length() == 0) {
954         return "";
955     }
956     if (status != U_ZERO_ERROR) {
957         return "";
958     }
959     icu::Locale locale = icu::Locale::forLanguageTag(displayLocale, status);
960     if (status != U_ZERO_ERROR) {
961         return "";
962     }
963     icu::UnicodeString unistr;
964     icu::UnicodeString displayRegion;
965     std::string result;
966     if (overrideSupportedRegions.find(displayLocale) != overrideSupportedRegions.end()) {
967         result = GetDisplayOverrideRegion(region, displayLocale);
968     } else {
969         originLocale.getDisplayCountry(locale, displayRegion);
970         displayRegion.toUTF8String(result);
971     }
972     if (sentenceCase) {
973         char ch = static_cast<char>(toupper(result[0]));
974         return result.replace(0, 1, 1, ch);
975     }
976     return result;
977 }
978 
IsRTL(const string & locale)979 bool LocaleConfig::IsRTL(const string &locale)
980 {
981     icu::Locale curLocale(locale.c_str());
982     return curLocale.isRightToLeft();
983 }
984 
parseExtension(const std::string & extension,std::map<std::string,std::string> & map)985 void parseExtension(const std::string &extension, std::map<std::string, std::string> &map)
986 {
987     std::string pattern = "-..-";
988     std::regex express(pattern);
989 
990     std::regex_token_iterator<std::string::const_iterator> begin1(extension.cbegin(), extension.cend(), express);
991     std::regex_token_iterator<std::string::const_iterator> begin2(extension.cbegin(), extension.cend(), express, -1);
992     begin2++;
993     for (; begin1 != std::sregex_token_iterator() && begin2 != std::sregex_token_iterator(); begin1++, begin2++) {
994         map.insert(std::pair<std::string, std::string>(begin1->str(), begin2->str()));
995     }
996 }
997 
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)998 void setExtension(std::string &extension, const std::string &tag, const std::set<string> &validValue,
999     const std::map<std::string, std::string> &extensionMap,
1000     const std::map<std::string, std::string> &defaultExtensionMap)
1001 {
1002     std::string value;
1003     auto it = extensionMap.find(tag);
1004     if (it != extensionMap.end()) {
1005         value = it->second;
1006         if (validValue.find(value) == validValue.end()) {
1007             return;
1008         } else {
1009             extension += tag;
1010             extension += value;
1011         }
1012     } else {
1013         it = defaultExtensionMap.find(tag);
1014         if (it != defaultExtensionMap.end()) {
1015             value = it->second;
1016             if (validValue.find(value) == validValue.end()) {
1017                 return;
1018             } else {
1019                 extension += tag;
1020                 extension += value;
1021             }
1022         }
1023     }
1024 }
1025 
setOtherExtension(std::string & extension,std::map<std::string,std::string> & extensionMap,std::map<std::string,std::string> & defaultExtensionMap)1026 void setOtherExtension(std::string &extension, std::map<std::string, std::string> &extensionMap,
1027     std::map<std::string, std::string> &defaultExtensionMap)
1028 {
1029     std::set<std::string> tags;
1030     tags.insert("-ca-");
1031     tags.insert("-co-");
1032     tags.insert("-kn-");
1033     tags.insert("-kf-");
1034     tags.insert("-nu-");
1035     tags.insert("-hc-");
1036 
1037     for (auto it = tags.begin(); it != tags.end(); it++) {
1038         extensionMap.erase(*it);
1039         defaultExtensionMap.erase(*it);
1040     }
1041 
1042     for (auto it = defaultExtensionMap.begin(); it != defaultExtensionMap.end(); it++) {
1043         extensionMap.insert(std::pair<std::string, std::string>(it->first, it->second));
1044     }
1045 
1046     for (auto it = extensionMap.begin(); it != extensionMap.end(); it++) {
1047         extension += it->first;
1048         extension += it->second;
1049     }
1050 }
1051 
GetValidLocale(const std::string & localeTag)1052 std::string LocaleConfig::GetValidLocale(const std::string &localeTag)
1053 {
1054     std::string baseLocale = "";
1055     std::string extension = "";
1056     std::size_t found = localeTag.find("-u-");
1057     baseLocale = localeTag.substr(0, found);
1058     if (found != std::string::npos) {
1059         extension = localeTag.substr(found);
1060     }
1061     std::map<std::string, std::string> extensionMap;
1062     if (extension != "") {
1063         parseExtension(extension, extensionMap);
1064     }
1065 
1066     std::string systemLocaleTag = GetSystemLocale();
1067     std::string defaultExtension = "";
1068     found = systemLocaleTag.find("-u-");
1069     if (found != std::string::npos) {
1070         defaultExtension = systemLocaleTag.substr(found);
1071     }
1072     std::map<std::string, std::string> defaultExtensionMap;
1073     if (defaultExtension != "") {
1074         parseExtension(defaultExtension, defaultExtensionMap);
1075     }
1076 
1077     std::string ext = "";
1078     setExtension(ext, "-ca-", validCaTag, extensionMap, defaultExtensionMap);
1079     setExtension(ext, "-co-", validCoTag, extensionMap, defaultExtensionMap);
1080     setExtension(ext, "-kn-", validKnTag, extensionMap, defaultExtensionMap);
1081     setExtension(ext, "-kf-", validKfTag, extensionMap, defaultExtensionMap);
1082     setExtension(ext, "-nu-", validNuTag, extensionMap, defaultExtensionMap);
1083     setExtension(ext, "-hc-", validHcTag, extensionMap, defaultExtensionMap);
1084 
1085     std::string otherExt = "";
1086     setOtherExtension(otherExt, extensionMap, defaultExtensionMap);
1087     if (ext != "" || otherExt != "") {
1088         return baseLocale + "-u" + ext + otherExt;
1089     } else {
1090         return baseLocale;
1091     }
1092 }
1093 
Is24HourClock()1094 bool LocaleConfig::Is24HourClock()
1095 {
1096     std::string is24Hour = ReadSystemParameter(HOUR_KEY, CONFIG_LEN);
1097     if (is24Hour.empty()) {
1098         return false;
1099     }
1100     if (is24Hour.compare("true") == 0) {
1101         return true;
1102     }
1103     return false;
1104 }
1105 
Set24HourClock(bool option)1106 bool LocaleConfig::Set24HourClock(bool option)
1107 {
1108     if (!CheckPermission()) {
1109         return false;
1110     }
1111     std::string optionStr = "";
1112     if (option) {
1113         optionStr = "true";
1114     } else {
1115         optionStr = "false";
1116     }
1117     if (SetParameter(HOUR_KEY, optionStr.data()) == 0) {
1118 #ifdef SUPPORT_GRAPHICS
1119         auto appMgrClient = std::make_unique<AppExecFwk::AppMgrClient>();
1120         AppExecFwk::Configuration configuration;
1121         configuration.AddItem(AAFwk::GlobalConfigurationKey::SYSTEM_HOUR, optionStr);
1122         appMgrClient->UpdateConfiguration(configuration);
1123 
1124         OHOS::AAFwk::Want timeChangeWant;
1125         timeChangeWant.SetAction(OHOS::EventFwk::CommonEventSupport::COMMON_EVENT_TIME_CHANGED);
1126         OHOS::EventFwk::CommonEventData event(timeChangeWant);
1127         if (!OHOS::EventFwk::CommonEventManager::PublishCommonEvent(event)) {
1128             HiLog::Info(LABEL, "Failed to Publish event %{public}s", timeChangeWant.GetAction().c_str());
1129             return false;
1130         }
1131 #endif
1132         return true;
1133     }
1134     return false;
1135 }
1136 
SetUsingLocalDigit(bool flag)1137 bool LocaleConfig::SetUsingLocalDigit(bool flag)
1138 {
1139     if (!CheckPermission()) {
1140         return false;
1141     }
1142     std::string locale = GetSystemLocale();
1143     LocaleInfo localeInfo(locale);
1144     std::string language = localeInfo.GetLanguage();
1145     if (localDigitMap.find(language) == localDigitMap.end()) {
1146         return false;
1147     }
1148     std::string numberSystem = "-nu-" + localDigitMap.at(language);
1149     if (flag) {
1150         if (locale.find("-u-") == std::string::npos) {
1151             locale += "-u" + numberSystem;
1152         } else if (locale.find("-nu-") == std::string::npos) {
1153             locale += numberSystem;
1154         } else {
1155             std::string oldNumberSystem = "-nu-" + localeInfo.GetNumberingSystem();
1156             locale.replace(locale.find("-nu-"), oldNumberSystem.length(), numberSystem);
1157         }
1158     } else {
1159         size_t pos = locale.find(numberSystem);
1160         if (pos != std::string::npos) {
1161             locale.replace(pos, numberSystem.length(), "");
1162         }
1163         // 2 is string -u length
1164         if (locale.find("-u") == (locale.length() - 2)) {
1165             // 2 is string -u length
1166             locale.resize(locale.length() - 2);
1167         }
1168     }
1169     if (!SetSystemLocale(locale)) {
1170         return false;
1171     }
1172     return true;
1173 }
1174 
GetUsingLocalDigit()1175 bool LocaleConfig::GetUsingLocalDigit()
1176 {
1177     std::string locale = GetSystemLocale();
1178     LocaleInfo localeInfo(locale);
1179     std::string language = localeInfo.GetLanguage();
1180     if (localDigitMap.find(language) == localDigitMap.end()) {
1181         return false;
1182     }
1183     std::string localNumberSystem = localDigitMap.at(language);
1184     if (localNumberSystem.compare(localeInfo.GetNumberingSystem()) != 0) {
1185         return false;
1186     }
1187     return true;
1188 }
1189 
UpdateSystemLocale(const std::string & language)1190 bool LocaleConfig::UpdateSystemLocale(const std::string &language)
1191 {
1192     UErrorCode status = U_ZERO_ERROR;
1193     icu::Locale languageLocale = icu::Locale::forLanguageTag(language.c_str(), status);
1194     if (U_FAILURE(status)) {
1195         return false;
1196     }
1197     std::string lang = languageLocale.getLanguage();
1198     std::string script = languageLocale.getScript();
1199 
1200     std::string systemLocaleTag = GetSystemLocale();
1201     icu::Locale systemLocale = icu::Locale::forLanguageTag(systemLocaleTag.c_str(), status);
1202     if (U_FAILURE(status)) {
1203         return false;
1204     }
1205     std::string region = systemLocale.getCountry();
1206 
1207     std::string extendParam;
1208     size_t pos = systemLocaleTag.find("-u-");
1209     if (pos < systemLocaleTag.length()) {
1210         extendParam = systemLocaleTag.substr(pos);
1211     }
1212 
1213     std::string finalLocaleTag = lang;
1214     std::string splitor = "-";
1215     if (script.length() > 0) {
1216         finalLocaleTag += splitor + script;
1217     }
1218     if (region.length() > 0) {
1219         finalLocaleTag += splitor + region;
1220     }
1221     if (extendParam.length() > 0) {
1222         finalLocaleTag += extendParam;
1223     }
1224     return SetSystemLocale(finalLocaleTag);
1225 }
1226 
GetBlockedLanguages()1227 std::unordered_set<std::string> LocaleConfig::GetBlockedLanguages()
1228 {
1229     return blockedLanguages;
1230 }
1231 
GetBlockedRegions()1232 std::unordered_set<std::string> LocaleConfig::GetBlockedRegions()
1233 {
1234     return blockedRegions;
1235 }
1236 
GetLanguageBlockedRegions()1237 std::unordered_set<std::string> LocaleConfig::GetLanguageBlockedRegions()
1238 {
1239     std::string systemLanguage = LocaleConfig::GetSystemLanguage();
1240     if (blockedLanguageRegions.find(systemLanguage) != blockedLanguageRegions.end()) {
1241         return blockedLanguageRegions[systemLanguage];
1242     }
1243     std::unordered_set<std::string> emptyResult;
1244     return emptyResult;
1245 }
1246 } // namespace I18n
1247 } // namespace Global
1248 } // namespace OHOS
1249