• 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         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 &region)
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 &region)
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 &region)
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> &regions = 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 &region)
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 &region, 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 &region, 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