• 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 <common_event_manager.h>
21 #include <common_event_publish_info.h>
22 #include <common_event_support.h>
23 #endif
24 #include <cctype>
25 #include "config_policy_utils.h"
26 #include "i18n_hilog.h"
27 #include "ipc_skeleton.h"
28 #include "libxml/parser.h"
29 #include "locale_info.h"
30 #include "locale_matcher.h"
31 #include "unicode/localebuilder.h"
32 #include "unicode/locdspnm.h"
33 #include "unicode/locid.h"
34 #include "unicode/smpdtfmt.h"
35 #include "ohos/init_data.h"
36 #include "parameter.h"
37 #include "securec.h"
38 #include "string_ex.h"
39 #include "ucase.h"
40 #include "ulocimp.h"
41 #include "unicode/unistr.h"
42 #include "ureslocs.h"
43 #include "unicode/ustring.h"
44 #include "ustr_imp.h"
45 #include "utils.h"
46 #include "tokenid_kit.h"
47 #include "locale_config.h"
48 
49 namespace OHOS {
50 namespace Global {
51 namespace I18n {
52 using namespace std;
53 const char *LocaleConfig::LANGUAGE_KEY = "persist.global.language";
54 const char *LocaleConfig::LOCALE_KEY = "persist.global.locale";
55 const char *LocaleConfig::HOUR_KEY = "persist.global.is24Hour";
56 const char *LocaleConfig::UPGRADE_LOCALE_KEY = "persist.global.upgrade_locale";
57 const char *LocaleConfig::DEFAULT_LOCALE_KEY = "const.global.locale";
58 const char *LocaleConfig::DEFAULT_LANGUAGE_KEY = "const.global.language";
59 const char *LocaleConfig::DEFAULT_REGION_KEY = "const.global.region";
60 const char *LocaleConfig::SIM_COUNTRY_CODE_KEY = "telephony.sim.countryCode0";
61 const char *LocaleConfig::SUPPORTED_LOCALES_NAME = "supported_locales";
62 const char *LocaleConfig::REGIONS_LANGUAGES_PATH = "etc/xml/i18n_param_config.xml";
63 const char *LocaleConfig::REGIONS_LANGUAGES_NAME = "i18n_param_config";
64 const char *LocaleConfig::SUPPORTED_REGIONS_NAME = "supported_regions";
65 const char *LocaleConfig::WHITE_LANGUAGES_NAME = "white_languages";
66 const char *LocaleConfig::FORBIDDEN_LANGUAGES_NAME = "forbidden_languages";
67 const char *LocaleConfig::FORBIDDEN_REGIONS_NAME = "forbidden_regions";
68 const char *LocaleConfig::SUPPORTED_LOCALES_PATH = "/system/usr/ohos_locale_config/supported_locales.xml";
69 const char *LocaleConfig::SUPPORTED_LOCALES_OLD_PATH = "/system/usr/ohos_locale_config/supported_locales_old.xml";
70 const char *LocaleConfig::SUPPORT_LOCALES_PATH = "/etc/ohos_lang_config/supported_locales.xml";
71 const char *LocaleConfig::SUPPORT_LOCALES_NAME = "supported_locales";
72 const char *LocaleConfig::DIALECT_LANGS_PATH = "/system/usr/ohos_locale_config/dialect_languages.xml";
73 const char *LocaleConfig::DIALECT_LANGS_NAME = "dialect_langs";
74 const char *LocaleConfig::OVERRIDE_SUPPORTED_REGIONS_NAME = "supported_regions";
75 const char *LocaleConfig::OVERRIDE_SUPPORTED_REGIONS_PATH =
76     "/system/usr/ohos_locale_config/region/supported_regions.xml";
77 const char *LocaleConfig::DEFAULT_LOCALE = "en-Latn";
78 const char *LocaleConfig::supportLocalesTag = "supported_locales";
79 const char *LocaleConfig::LANG_PATH = "/etc/ohos_lang_config/";
80 const char *LocaleConfig::REGION_PATH = "/system/usr/ohos_locale_config/region/";
81 const char *LocaleConfig::rootTag = "languages";
82 const char *LocaleConfig::secondRootTag = "lang";
83 const char *LocaleConfig::rootRegion = "regions";
84 const char *LocaleConfig::secondRootRegion = "region";
85 const char *LocaleConfig::NUMBER_SYSTEM_KEY = "-nu-";
86 const std::string LocaleConfig::HOUR_EVENT_DATA = "24HourChange";
87 unordered_set<string> LocaleConfig::supportedLocales;
88 unordered_set<string> LocaleConfig::supportedLocalesV15;
89 unordered_set<string> LocaleConfig::supportLocales;
90 unordered_set<string> LocaleConfig::supportedRegions;
91 unordered_set<string> LocaleConfig::overrideSupportedRegions;
92 unordered_set<string> LocaleConfig::dialectLang;
93 unordered_set<string> LocaleConfig::blockedLanguages;
94 unordered_set<string> LocaleConfig::blockedRegions;
95 unordered_map<string, unordered_set<string>> LocaleConfig::blockedLanguageRegions;
96 unordered_set<string> LocaleConfig::whiteLanguages;
97 std::set<std::string> LocaleConfig::extendWhiteLanguageList;
98 std::set<std::string> LocaleConfig::extendWhiteLanguageListV15;
99 unordered_map<string, string> LocaleConfig::dialectMap {
100     { "es-Latn-419", "es-Latn-419" },
101     { "es-Latn-BO", "es-Latn-419" },
102     { "es-Latn-BR", "es-Latn-419" },
103     { "es-Latn-BZ", "es-Latn-419" },
104     { "es-Latn-CL", "es-Latn-419" },
105     { "es-Latn-CO", "es-Latn-419" },
106     { "es-Latn-CR", "es-Latn-419" },
107     { "es-Latn-CU", "es-Latn-419" },
108     { "es-Latn-DO", "es-Latn-419" },
109     { "es-Latn-EC", "es-Latn-419" },
110     { "es-Latn-GT", "es-Latn-419" },
111     { "es-Latn-HN", "es-Latn-419" },
112     { "es-Latn-MX", "es-Latn-419" },
113     { "es-Latn-NI", "es-Latn-419" },
114     { "es-Latn-PA", "es-Latn-419" },
115     { "es-Latn-PE", "es-Latn-419" },
116     { "es-Latn-PR", "es-Latn-419" },
117     { "es-Latn-PY", "es-Latn-419" },
118     { "es-Latn-SV", "es-Latn-419" },
119     { "es-Latn-US", "es-Latn-419" },
120     { "es-Latn-UY", "es-Latn-419" },
121     { "es-Latn-VE", "es-Latn-419" },
122     { "pt-Latn-PT", "pt-Latn-PT" }
123 };
124 
125 unordered_map<string, string> LocaleConfig::dialectMapV15 {
126     { "es-Latn-419", "es-Latn-419" },
127     { "es-Latn-BO", "es-Latn-419" },
128     { "es-Latn-BR", "es-Latn-419" },
129     { "es-Latn-BZ", "es-Latn-419" },
130     { "es-Latn-CL", "es-Latn-419" },
131     { "es-Latn-CO", "es-Latn-419" },
132     { "es-Latn-CR", "es-Latn-419" },
133     { "es-Latn-CU", "es-Latn-419" },
134     { "es-Latn-DO", "es-Latn-419" },
135     { "es-Latn-EC", "es-Latn-419" },
136     { "es-Latn-GT", "es-Latn-419" },
137     { "es-Latn-HN", "es-Latn-419" },
138     { "es-Latn-MX", "es-Latn-419" },
139     { "es-Latn-NI", "es-Latn-419" },
140     { "es-Latn-PA", "es-Latn-419" },
141     { "es-Latn-PE", "es-Latn-419" },
142     { "es-Latn-PR", "es-Latn-419" },
143     { "es-Latn-PY", "es-Latn-419" },
144     { "es-Latn-SV", "es-Latn-419" },
145     { "es-Latn-US", "es-Latn-419" },
146     { "es-Latn-UY", "es-Latn-419" },
147     { "es-Latn-VE", "es-Latn-419" },
148     { "pt-Latn-PT", "pt-Latn-PT" },
149     { "en-Latn-US", "en-Latn-US" }
150 };
151 
152 unordered_map<string, string> LocaleConfig::localDigitMap {
153     { "ar", "arab" },
154     { "as", "beng" },
155     { "bn", "beng" },
156     { "fa", "arabext" },
157     { "mr", "deva" },
158     { "my", "mymr" },
159     { "ne", "deva" },
160     { "ur", "latn" }
161 };
162 
163 std::unordered_map<std::string, std::vector<std::string>> LocaleConfig::dialectLanguages {
164     { "en-Latn", { "en-Latn-US", "en-Latn-GB" } },
165     { "pt-Latn", { "pt-Latn-PT", "pt-Latn-BR" } },
166     { "zh-Hant", { "zh-Hant-HK", "zh-Hant-TW" } },
167 };
168 
169 std::unordered_map<std::string, std::string> LocaleConfig::resourceIdMap {
170     { "zh", "zh-Hans" },
171     { "zh-HK", "zh-Hant-HK" },
172     { "zh-TW", "zh-Hant" },
173     { "az", "az-Latn" },
174     { "bs", "bs-Latn" },
175     { "jv", "jv-Latn" },
176     { "uz", "uz-Latn" },
177     { "mn", "mn-Cyrl" },
178 };
179 
180 std::map<std::string, std::string> LocaleConfig::supportedDialectLocales;
181 std::map<string, string> LocaleConfig::locale2DisplayName {};
182 std::map<string, string> LocaleConfig::region2DisplayName {};
183 std::string LocaleConfig::currentDialectLocale = "";
184 std::string LocaleConfig::currentOverrideRegion = "";
185 std::mutex LocaleConfig::dialectLocaleMutex;
186 std::mutex LocaleConfig::region2DisplayNameMutex;
187 std::mutex LocaleConfig::locale2DisplayNameMutex;
188 
189 set<std::string> LocaleConfig::validCaTag {
190     "buddhist",
191     "chinese",
192     "coptic",
193     "dangi",
194     "ethioaa",
195     "ethiopic",
196     "gregory",
197     "hebrew",
198     "indian",
199     "islamic",
200     "islamic-umalqura",
201     "islamic-tbla",
202     "islamic-civil",
203     "islamic-rgsa",
204     "iso8601",
205     "japanese",
206     "persian",
207     "roc",
208     "islamicc",
209 };
210 set<std::string> LocaleConfig::validCoTag {
211     "big5han",
212     "compat",
213     "dict",
214     "direct",
215     "ducet",
216     "eor",
217     "gb2312",
218     "phonebk",
219     "phonetic",
220     "pinyin",
221     "reformed",
222     "searchjl",
223     "stroke",
224     "trad",
225     "unihan",
226     "zhuyin",
227 };
228 set<std::string> LocaleConfig::validKnTag {
229     "true",
230     "false",
231 };
232 set<std::string> LocaleConfig::validKfTag {
233     "upper",
234     "lower",
235     "false",
236 };
237 set<std::string> LocaleConfig::validNuTag {
238     "adlm", "ahom", "arab", "arabext", "bali", "beng",
239     "bhks", "brah", "cakm", "cham", "deva", "diak",
240     "fullwide", "gong", "gonm", "gujr", "guru", "hanidec",
241     "hmng", "hmnp", "java", "kali", "khmr", "knda",
242     "lana", "lanatham", "laoo", "latn", "lepc", "limb",
243     "mathbold", "mathdbl", "mathmono", "mathsanb", "mathsans", "mlym",
244     "modi", "mong", "mroo", "mtei", "mymr", "mymrshan",
245     "mymrtlng", "newa", "nkoo", "olck", "orya", "osma",
246     "rohg", "saur", "segment", "shrd", "sind", "sinh",
247     "sora", "sund", "takr", "talu", "tamldec", "telu",
248     "thai", "tibt", "tirh", "vaii", "wara", "wcho",
249 };
250 set<std::string> LocaleConfig::validHcTag {
251     "h12",
252     "h23",
253     "h11",
254     "h24",
255 };
256 
257 static unordered_map<string, string> g_languageMap = {
258     { "zh-Hans", "zh-Hans" },
259     { "zh-Hant-HK", "zh-Hant-HK" },
260     { "zh-Hant", "zh-Hant" },
261     { "my-Qaag", "my-Qaag" },
262     { "es-Latn-419", "es-419" },
263     { "es-Latn-US", "es-419" },
264     { "az-Latn", "az-Latn" },
265     { "bs-Latn", "bs-Latn" },
266     { "en-Latn-US", "en" },
267     { "en-Qaag", "en-Qaag" },
268     { "uz-Latn", "uz-Latn" },
269     { "sr-Latn", "sr-Latn" },
270     { "jv-Latn", "jv-Latn" },
271     { "pt-Latn-BR", "pt-BR" },
272     { "pa-Guru", "pa-Guru" },
273     { "mai-Deva", "mai-Deva" }
274 };
275 
Adjust(const string & origin)276 string Adjust(const string &origin)
277 {
278     auto iter = g_languageMap.find(origin);
279     if (iter != g_languageMap.end()) {
280         return iter->second;
281     }
282     for (iter = g_languageMap.begin(); iter != g_languageMap.end(); ++iter) {
283         string key = iter->first;
284         if (!origin.compare(0, key.length(), key)) {
285             return iter->second;
286         }
287     }
288     return origin;
289 }
290 
GetDisplayLanguageInner(const string & language,const string & displayLocaleTag,bool sentenceCase)291 string GetDisplayLanguageInner(const string &language, const string &displayLocaleTag, bool sentenceCase)
292 {
293     icu::UnicodeString unistr;
294     // 0 is the start position of language, 2 is the length of zh and fa
295     if (!language.compare(0, 2, "zh") || !language.compare(0, 2, "fa") || !language.compare(0, 2, "ro")) {
296         UErrorCode status = U_ZERO_ERROR;
297         icu::Locale displayLocale = icu::Locale::forLanguageTag(displayLocaleTag.c_str(), status);
298         if (status != U_ZERO_ERROR) {
299             return "";
300         }
301         icu::LocaleDisplayNames *dspNames = icu::LocaleDisplayNames::createInstance(displayLocale,
302             UDialectHandling::ULDN_DIALECT_NAMES);
303         icu::Locale tempLocale = icu::Locale::forLanguageTag(language.c_str(), status);
304         if (status != U_ZERO_ERROR) {
305             return "";
306         }
307         if (dspNames != nullptr) {
308             dspNames->localeDisplayName(tempLocale, unistr);
309             delete dspNames;
310         }
311     } else {
312         UErrorCode status = U_ZERO_ERROR;
313         icu::Locale displayLoc = icu::Locale::forLanguageTag(displayLocaleTag, status);
314         if (status != U_ZERO_ERROR) {
315             return "";
316         }
317         icu::Locale locale = icu::Locale::forLanguageTag(language, status);
318         if (status != U_ZERO_ERROR) {
319             return "";
320         }
321         locale.getDisplayName(displayLoc, unistr);
322     }
323     if (sentenceCase) {
324         UChar32 ch = ucase_toupper(unistr.char32At(0));
325         unistr.replace(0, 1, ch);
326     }
327     string out;
328     unistr.toUTF8String(out);
329     return out;
330 }
331 
332 bool LocaleConfig::listsInitialized = LocaleConfig::InitializeLists();
333 
GetSystemLanguage()334 string LocaleConfig::GetSystemLanguage()
335 {
336     std::string systemLanguage = ReadSystemParameter(LANGUAGE_KEY, CONFIG_LEN);
337     if (systemLanguage.empty()) {
338         systemLanguage = ReadSystemParameter(DEFAULT_LANGUAGE_KEY, CONFIG_LEN);
339     }
340     return systemLanguage;
341 }
342 
GetSystemRegion()343 string LocaleConfig::GetSystemRegion()
344 {
345     std::string systemRegion = GetCountry(LOCALE_KEY);
346     if (systemRegion.empty()) {
347         systemRegion = GetCountry(DEFAULT_LOCALE_KEY);
348     }
349     if (systemRegion.empty()) {
350         return "CN";
351     }
352     return systemRegion;
353 }
354 
GetCountry(const string & parameter)355 string LocaleConfig::GetCountry(const string& parameter)
356 {
357     std::string systemRegion = ReadSystemParameter(parameter.c_str(), CONFIG_LEN);
358     if (systemRegion.empty()) {
359         HILOG_INFO_I18N("GetCountry: ReadSystemParameter %{public}s failed", parameter.c_str());
360         return systemRegion;
361     }
362     UErrorCode status = U_ZERO_ERROR;
363     icu::Locale origin = icu::Locale::forLanguageTag(systemRegion, status);
364     if (U_SUCCESS(status)) {
365         const char* country = origin.getCountry();
366         if (country != nullptr) {
367             return country;
368         }
369         HILOG_INFO_I18N("GetCountry: %{public}s get failed, country is nullptr", parameter.c_str());
370     } else {
371         HILOG_INFO_I18N("GetCountry: %{public}s get failed, U_SUCCESS is false", parameter.c_str());
372     }
373     return "";
374 }
375 
GetSystemLocale()376 string LocaleConfig::GetSystemLocale()
377 {
378     std::string systemLocale = ReadSystemParameter(LOCALE_KEY, CONFIG_LEN);
379     if (systemLocale.empty()) {
380         systemLocale = ReadSystemParameter(DEFAULT_LOCALE_KEY, CONFIG_LEN);
381     }
382     return systemLocale;
383 }
384 
IsValidLanguage(const string & language)385 bool LocaleConfig::IsValidLanguage(const string &language)
386 {
387     string::size_type size = language.size();
388     if ((size != LANGUAGE_LEN) && (size != LANGUAGE_LEN + 1)) {
389         return false;
390     }
391     for (size_t i = 0; i < size; ++i) {
392         if ((language[i] > 'z') || (language[i] < 'a')) {
393             return false;
394         }
395     }
396     return true;
397 }
398 
IsValidRegion(const string & region)399 bool LocaleConfig::IsValidRegion(const string &region)
400 {
401     string::size_type size = region.size();
402     if (size != LocaleInfo::REGION_LEN) {
403         return false;
404     }
405     for (size_t i = 0; i < LocaleInfo::REGION_LEN; ++i) {
406         if ((region[i] > 'Z') || (region[i] < 'A')) {
407             return false;
408         }
409     }
410     return true;
411 }
412 
IsValidTag(const string & tag)413 bool LocaleConfig::IsValidTag(const string &tag)
414 {
415     if (!tag.size()) {
416         return false;
417     }
418     vector<string> splits;
419     Split(tag, "-", splits);
420     if (!IsValidLanguage(splits[0])) {
421         return false;
422     }
423     return true;
424 }
425 
Split(const string & src,const string & sep,vector<string> & dest)426 void LocaleConfig::Split(const string &src, const string &sep, vector<string> &dest)
427 {
428     string::size_type begin = 0;
429     string::size_type end = src.find(sep);
430     while (end != string::npos) {
431         dest.push_back(src.substr(begin, end - begin));
432         begin = end + sep.size();
433         end = src.find(sep, begin);
434     }
435     if (begin != src.size()) {
436         dest.push_back(src.substr(begin));
437     }
438 }
439 
Split(const string & src,const string & sep,std::unordered_set<string> & dest)440 void LocaleConfig::Split(const string &src, const string &sep, std::unordered_set<string> &dest)
441 {
442     string::size_type begin = 0;
443     string::size_type end = src.find(sep);
444     while (end != string::npos) {
445         dest.insert(src.substr(begin, end - begin));
446         begin = end + sep.size();
447         end = src.find(sep, begin);
448     }
449     if (begin != src.size()) {
450         dest.insert(src.substr(begin));
451     }
452 }
453 
454 // language in white languages should have script.
GetSystemLanguages(vector<string> & ret)455 void LocaleConfig::GetSystemLanguages(vector<string> &ret)
456 {
457     std::copy(whiteLanguages.begin(), whiteLanguages.end(), std::back_inserter(ret));
458 }
459 
GetSupportedLocales()460 const unordered_set<string>& LocaleConfig::GetSupportedLocales()
461 {
462     return supportedLocales;
463 }
464 
GetSupportedLocalesV15()465 const unordered_set<string>& LocaleConfig::GetSupportedLocalesV15()
466 {
467     return supportedLocalesV15;
468 }
469 
GetSupportedRegions()470 const unordered_set<string>& LocaleConfig::GetSupportedRegions()
471 {
472     return supportedRegions;
473 }
474 
GetSystemCountries(vector<string> & ret)475 void LocaleConfig::GetSystemCountries(vector<string> &ret)
476 {
477     std::copy(supportedRegions.begin(), supportedRegions.end(), std::back_inserter(ret));
478 }
479 
IsSuggested(const string & language)480 bool LocaleConfig::IsSuggested(const string &language)
481 {
482     unordered_set<string> relatedLocales;
483     vector<string> simCountries;
484     GetCountriesFromSim(simCountries);
485     GetRelatedLocales(relatedLocales, simCountries);
486     for (auto iter = relatedLocales.begin(); iter != relatedLocales.end();) {
487         if (extendWhiteLanguageList.find(*iter) == extendWhiteLanguageList.end()) {
488             iter = relatedLocales.erase(iter);
489         } else {
490             ++iter;
491         }
492     }
493     string mainLanguage = GetMainLanguage(language, dialectMap);
494     return relatedLocales.find(mainLanguage) != relatedLocales.end();
495 }
496 
IsSuggested(const std::string & language,const std::string & region)497 bool LocaleConfig::IsSuggested(const std::string &language, const std::string &region)
498 {
499     unordered_set<string> relatedLocales;
500     vector<string> countries { region };
501     GetRelatedLocales(relatedLocales, countries);
502     for (auto iter = relatedLocales.begin(); iter != relatedLocales.end();) {
503         if (extendWhiteLanguageList.find(*iter) == extendWhiteLanguageList.end()) {
504             iter = relatedLocales.erase(iter);
505         } else {
506             ++iter;
507         }
508     }
509     string mainLanguage = GetMainLanguage(language, dialectMap);
510     return relatedLocales.find(mainLanguage) != relatedLocales.end();
511 }
512 
IsSuggestedV15(const string & language)513 bool LocaleConfig::IsSuggestedV15(const string &language)
514 {
515     unordered_set<string> relatedLocales;
516     vector<string> simCountries;
517     GetCountriesFromSim(simCountries);
518     GetRelatedLocalesV15(relatedLocales, simCountries);
519     auto iter = relatedLocales.begin();
520     while (iter != relatedLocales.end()) {
521         if (extendWhiteLanguageListV15.find(*iter) == extendWhiteLanguageListV15.end()) {
522             iter = relatedLocales.erase(iter);
523         } else {
524             ++iter;
525         }
526     }
527     string mainLanguage = GetMainLanguage(language, dialectMapV15);
528     return relatedLocales.find(mainLanguage) != relatedLocales.end();
529 }
530 
IsSuggestedV15(const std::string & language,const std::string & region)531 bool LocaleConfig::IsSuggestedV15(const std::string &language, const std::string &region)
532 {
533     unordered_set<string> relatedLocales;
534     vector<string> countries { region };
535     GetRelatedLocalesV15(relatedLocales, countries);
536     auto iter = relatedLocales.begin();
537     while (iter != relatedLocales.end()) {
538         if (extendWhiteLanguageListV15.find(*iter) == extendWhiteLanguageListV15.end()) {
539             iter = relatedLocales.erase(iter);
540         } else {
541             ++iter;
542         }
543     }
544     string mainLanguage = GetMainLanguage(language, dialectMapV15);
545     return relatedLocales.find(mainLanguage) != relatedLocales.end();
546 }
547 
ExtendWhiteLanguages()548 void LocaleConfig::ExtendWhiteLanguages()
549 {
550     UErrorCode status = U_ZERO_ERROR;
551     for (auto iter = whiteLanguages.begin(); iter != whiteLanguages.end(); ++iter) {
552         extendWhiteLanguageList.insert(*iter);
553         extendWhiteLanguageListV15.insert(*iter);
554         icu::Locale locale = icu::Locale::forLanguageTag((*iter).c_str(), status);
555         locale.addLikelySubtags(status);
556         if (U_FAILURE(status)) {
557             HILOG_INFO_I18N("create Locale object for %{public}s failed.", (*iter).c_str());
558             continue;
559         }
560         const char* baseName = locale.getBaseName();
561         if (baseName != nullptr) {
562             std::string baseNameStr(baseName);
563             std::replace(baseNameStr.begin(), baseNameStr.end(), '_', '-');
564             extendWhiteLanguageList.insert(baseNameStr);
565             extendWhiteLanguageListV15.insert(baseNameStr);
566         }
567         const char* language = locale.getLanguage();
568         if (language != nullptr) {
569             std::string languageStr(language);
570             ExtendLanguageWithScript(languageStr);
571         }
572     }
573 }
574 
ExtendLanguageWithScript(const std::string & languageStr)575 void LocaleConfig::ExtendLanguageWithScript(const std::string &languageStr)
576 {
577     if (languageStr.empty()) {
578         HILOG_INFO_I18N("ExtendLanguageWithScript languageStr is empty.");
579         return;
580     }
581     string mainLanguage = GetMainLanguage(languageStr, dialectMap);
582     if (!mainLanguage.empty()) {
583         extendWhiteLanguageList.insert(mainLanguage);
584     }
585 }
586 
GetRelatedLocales(unordered_set<string> & relatedLocales,vector<string> countries)587 void LocaleConfig::GetRelatedLocales(unordered_set<string> &relatedLocales, vector<string> countries)
588 {
589     // remove unsupported countries
590     const unordered_set<string> &regions = GetSupportedRegions();
591     auto iter = countries.begin();
592     while (iter != countries.end()) {
593         if (regions.find(*iter) == regions.end()) {
594             iter = countries.erase(iter);
595         } else {
596             ++iter;
597         }
598     }
599     const unordered_set<string> &locales = GetSupportedLocales();
600     for (const string &locale : locales) {
601         bool find = false;
602         for (string &country : countries) {
603             if (locale.find(country) != string::npos) {
604                 find = true;
605                 break;
606             }
607         }
608         if (!find) {
609             continue;
610         }
611         string mainLanguage = GetMainLanguage(locale, dialectMap);
612         if (!mainLanguage.empty()) {
613             relatedLocales.insert(mainLanguage);
614         }
615     }
616 }
617 
GetRelatedLocalesV15(unordered_set<string> & relatedLocales,vector<string> countries)618 void LocaleConfig::GetRelatedLocalesV15(unordered_set<string> &relatedLocales, vector<string> countries)
619 {
620     // remove unsupported countries
621     const unordered_set<string> &regions = GetSupportedRegions();
622     auto iter = countries.begin();
623     while (iter != countries.end()) {
624         if (regions.find(*iter) == regions.end()) {
625             iter = countries.erase(iter);
626         } else {
627             ++iter;
628         }
629     }
630     const unordered_set<string> &locales = GetSupportedLocalesV15();
631     for (const string &locale : locales) {
632         bool find = false;
633         for (const string &country : countries) {
634             if (locale.find(country) != string::npos) {
635                 find = true;
636                 break;
637             }
638         }
639         if (!find) {
640             continue;
641         }
642         string mainLanguage = GetMainLanguage(locale, dialectMapV15);
643         if (!mainLanguage.empty()) {
644             relatedLocales.insert(mainLanguage);
645         }
646     }
647 }
648 
GetCountriesFromSim(vector<string> & simCountries)649 void LocaleConfig::GetCountriesFromSim(vector<string> &simCountries)
650 {
651     simCountries.push_back(GetSystemRegion());
652     char value[CONFIG_LEN];
653     int code = GetParameter(SIM_COUNTRY_CODE_KEY, "", value, CONFIG_LEN);
654     if (code > 0) {
655         simCountries.push_back(value);
656     }
657 }
658 
GetListFromFile(const char * path,const char * resourceName,unordered_set<string> & ret)659 void LocaleConfig::GetListFromFile(const char *path, const char *resourceName, unordered_set<string> &ret)
660 {
661     xmlKeepBlanksDefault(0);
662     if (!path) {
663         return;
664     }
665     xmlDocPtr doc = xmlParseFile(path);
666     if (!doc) {
667         return;
668     }
669     xmlNodePtr cur = xmlDocGetRootElement(doc);
670     if (!cur || xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>(resourceName))) {
671         xmlFreeDoc(doc);
672         return;
673     }
674     cur = cur->xmlChildrenNode;
675     xmlChar *content = nullptr;
676     while (cur != nullptr) {
677         content = xmlNodeGetContent(cur);
678         if (content != nullptr) {
679             ret.insert(reinterpret_cast<const char*>(content));
680             xmlFree(content);
681             cur = cur->next;
682         } else {
683             break;
684         }
685     }
686     xmlFreeDoc(doc);
687 }
688 
ProcessForbiddenRegions(const unordered_set<string> & forbiddenRegions)689 void LocaleConfig::ProcessForbiddenRegions(const unordered_set<string> &forbiddenRegions)
690 {
691     for (auto it = forbiddenRegions.begin(); it != forbiddenRegions.end(); ++it) {
692         size_t pos = it->rfind("-");
693         std::string language = it->substr(0, pos);
694         std::string region = it->substr(pos + 1);
695         if (language.compare("*") == 0) {
696             blockedRegions.insert(region);
697         } else {
698             if (blockedLanguageRegions.find(language) == blockedLanguageRegions.end()) {
699                 blockedLanguageRegions[language] = { region };
700             } else {
701                 blockedLanguageRegions[language].insert(region);
702             }
703         }
704     }
705 }
706 
Expunge(unordered_set<string> & src,const unordered_set<string> & another)707 void LocaleConfig::Expunge(unordered_set<string> &src, const unordered_set<string> &another)
708 {
709     for (auto iter = src.begin(); iter != src.end();) {
710         if (another.find(*iter) != another.end()) {
711             iter = src.erase(iter);
712         } else {
713             ++iter;
714         }
715     }
716 }
717 
InitializeLists()718 bool LocaleConfig::InitializeLists()
719 {
720     SetHwIcuDirectory();
721     unordered_set<string> forbiddenRegions;
722     LoadRegionsLanguages(forbiddenRegions);
723     ProcessForbiddenRegions(forbiddenRegions);
724     Expunge(supportedRegions, blockedRegions);
725     Expunge(whiteLanguages, blockedLanguages);
726     GetListFromFile(SUPPORTED_LOCALES_PATH, SUPPORTED_LOCALES_NAME, supportedLocales);
727     GetListFromFile(SUPPORTED_LOCALES_OLD_PATH, SUPPORTED_LOCALES_NAME, supportedLocalesV15);
728     GetListFromFile(SUPPORT_LOCALES_PATH, SUPPORT_LOCALES_NAME, supportLocales);
729     GetListFromFile(OVERRIDE_SUPPORTED_REGIONS_PATH, OVERRIDE_SUPPORTED_REGIONS_NAME, overrideSupportedRegions);
730     GetListFromFile(DIALECT_LANGS_PATH, DIALECT_LANGS_NAME, dialectLang);
731     ExtendWhiteLanguages();
732     return true;
733 }
734 
LoadRegionsLanguages(unordered_set<std::string> & forbiddenRegions)735 void LocaleConfig::LoadRegionsLanguages(unordered_set<std::string>& forbiddenRegions)
736 {
737     char buf[MAX_PATH_LEN] = {0};
738     char* path = GetOneCfgFile(REGIONS_LANGUAGES_PATH, buf, MAX_PATH_LEN);
739     xmlKeepBlanksDefault(0);
740     if (!path) {
741         return;
742     }
743     xmlDocPtr doc = xmlParseFile(path);
744     if (!doc) {
745         return;
746     }
747     xmlNodePtr cur = xmlDocGetRootElement(doc);
748     if (!cur || xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>(REGIONS_LANGUAGES_NAME))) {
749         xmlFreeDoc(doc);
750         return;
751     }
752     cur = cur->xmlChildrenNode;
753     xmlChar *content = nullptr;
754     while (cur != nullptr) {
755         content = xmlNodeGetContent(cur);
756         if (content != nullptr && !xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>(SUPPORTED_REGIONS_NAME))) {
757             Split(reinterpret_cast<const char*>(content), ",", supportedRegions);
758         } else if (content != nullptr && !xmlStrcmp(cur->name,
759             reinterpret_cast<const xmlChar *>(WHITE_LANGUAGES_NAME))) {
760             Split(reinterpret_cast<const char*>(content), ",", whiteLanguages);
761         } else if (content != nullptr && !xmlStrcmp(cur->name,
762             reinterpret_cast<const xmlChar *>(FORBIDDEN_REGIONS_NAME))) {
763             Split(reinterpret_cast<const char*>(content), ",", forbiddenRegions);
764         } else if (content != nullptr && !xmlStrcmp(cur->name,
765             reinterpret_cast<const xmlChar *>(FORBIDDEN_LANGUAGES_NAME))) {
766             Split(reinterpret_cast<const char*>(content), ",", blockedLanguages);
767         }
768         if (content != nullptr) {
769             xmlFree(content);
770         }
771         cur = cur->next;
772     }
773     xmlFreeDoc(doc);
774 }
775 
GetMainLanguage(const string & language,std::unordered_map<std::string,std::string> selfDialectMap)776 string LocaleConfig::GetMainLanguage(const string &language,
777     std::unordered_map<std::string, std::string> selfDialectMap)
778 {
779     UErrorCode status = U_ZERO_ERROR;
780     icu::Locale origin = icu::Locale::forLanguageTag(language, status);
781     if (status != U_ZERO_ERROR) {
782         return "";
783     }
784     origin.addLikelySubtags(status);
785     if (status != U_ZERO_ERROR) {
786         return "";
787     }
788     icu::LocaleBuilder builder = icu::LocaleBuilder().setLanguage(origin.getLanguage()).
789         setScript(origin.getScript()).setRegion(origin.getCountry());
790     icu::Locale temp = builder.setExtension('u', "").build(status);
791     if (status != U_ZERO_ERROR) {
792         return "";
793     }
794     string fullLanguage = temp.toLanguageTag<string>(status);
795     if (status != U_ZERO_ERROR) {
796         return "";
797     }
798     if (selfDialectMap.find(fullLanguage) != selfDialectMap.end()) {
799         return selfDialectMap[fullLanguage];
800     }
801     builder.setRegion("");
802     temp = builder.build(status);
803     if (status != U_ZERO_ERROR) {
804         return "";
805     }
806     fullLanguage = temp.toLanguageTag<string>(status);
807     if (status != U_ZERO_ERROR) {
808         return "";
809     }
810     return fullLanguage;
811 }
812 
GetDisplayLanguage(const string & language,const string & displayLocale,bool sentenceCase)813 string LocaleConfig::GetDisplayLanguage(const string &language, const string &displayLocale, bool sentenceCase)
814 {
815     std::string result;
816     string adjust = Adjust(language);
817     if (adjust == language) {
818         UErrorCode status = U_ZERO_ERROR;
819         icu::Locale displayLoc = icu::Locale::forLanguageTag(displayLocale, status);
820         if (status != U_ZERO_ERROR) {
821             return PseudoLocalizationProcessor("");
822         }
823         icu::Locale locale = icu::Locale::forLanguageTag(language, status);
824         if (status != U_ZERO_ERROR) {
825             return PseudoLocalizationProcessor("");
826         }
827         icu::UnicodeString unistr;
828         std::string lang(locale.getLanguage());
829         if (dialectLang.find(lang) != dialectLang.end()) {
830             result = GetDisplayLanguageWithDialect(language, displayLocale);
831         }
832     }
833     if (result.empty()) {
834         result = GetDisplayLanguageInner(adjust, displayLocale, sentenceCase);
835     }
836     if (sentenceCase && !result.empty()) {
837         char ch = static_cast<char>(toupper(result[0]));
838         return PseudoLocalizationProcessor(result.replace(0, 1, 1, ch));
839     }
840     return PseudoLocalizationProcessor(result);
841 }
842 
ComputeLocale(const std::string & displayLocale)843 std::string LocaleConfig::ComputeLocale(const std::string &displayLocale)
844 {
845     if (supportedDialectLocales.size() == 0) {
846         xmlKeepBlanksDefault(0);
847         xmlDocPtr doc = xmlParseFile(SUPPORT_LOCALES_PATH);
848         if (!doc) {
849             return "";
850         }
851         xmlNodePtr cur = xmlDocGetRootElement(doc);
852         if (!cur || xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>(supportLocalesTag))) {
853             xmlFreeDoc(doc);
854             HILOG_INFO_I18N("can not parse language supported locale file");
855             return "";
856         }
857         cur = cur->xmlChildrenNode;
858         while (cur != nullptr) {
859             xmlChar *content = xmlNodeGetContent(cur);
860             if (content == nullptr) {
861                 HILOG_INFO_I18N("get xml node content failed");
862                 break;
863             }
864             std::map<std::string, std::string> localeInfoConfigs = {};
865             LocaleInfo localeinfo(reinterpret_cast<const char*>(content), localeInfoConfigs);
866             std::string maximizeLocale = localeinfo.Maximize();
867             const char* key = maximizeLocale.c_str();
868             const char* value = reinterpret_cast<const char*>(content);
869             SetSupportedDialectLocales(key, value);
870             xmlFree(content);
871             cur = cur->next;
872         }
873         xmlFreeDoc(doc);
874     }
875     std::map<std::string, std::string> configs = {};
876     LocaleInfo localeinfo(displayLocale, configs);
877     std::string maximizeLocale = localeinfo.Maximize();
878     if (supportedDialectLocales.find(maximizeLocale) != supportedDialectLocales.end()) {
879         return supportedDialectLocales.at(maximizeLocale);
880     }
881     return "";
882 }
883 
SetSupportedDialectLocales(const char * key,const char * value)884 void LocaleConfig::SetSupportedDialectLocales(const char* key, const char* value)
885 {
886     std::lock_guard<std::mutex> dialectLocaleLock(dialectLocaleMutex);
887     supportedDialectLocales.insert(
888         std::make_pair<std::string, std::string>(key, value));
889 }
890 
ReadLangData(const char * langDataPath)891 void LocaleConfig::ReadLangData(const char *langDataPath)
892 {
893     xmlKeepBlanksDefault(0);
894     if (langDataPath == nullptr) {
895         return;
896     }
897     xmlDocPtr doc = xmlParseFile(langDataPath);
898     if (!doc) {
899         HILOG_INFO_I18N("can not open language data file");
900         return;
901     }
902     xmlNodePtr cur = xmlDocGetRootElement(doc);
903     if (!cur || xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>(rootTag))) {
904         xmlFreeDoc(doc);
905         HILOG_INFO_I18N("parse language data file failed");
906         return;
907     }
908     cur = cur->xmlChildrenNode;
909     while (cur != nullptr && !xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>(secondRootTag))) {
910         xmlChar *langContents[ELEMENT_NUM] = { 0 }; // 2 represent langid, displayname;
911         xmlNodePtr langValue = cur->xmlChildrenNode;
912         bool xmlNodeNull = false;
913         for (size_t i = 0; i < ELEMENT_NUM && langValue != nullptr; i++) {
914             langContents[i] = xmlNodeGetContent(langValue);
915             langValue = langValue->next;
916             if (langContents[i] == nullptr) {
917                 xmlNodeNull = true;
918             }
919         }
920         if (!xmlNodeNull) {
921             // 0 represents langid index, 1 represents displayname index
922             const char* key = reinterpret_cast<const char *>(langContents[0]);
923             const char* value = reinterpret_cast<const char *>(langContents[1]);
924             SetLocale2DisplayName(key, value);
925         }
926         for (size_t i = 0; i < ELEMENT_NUM; i++) {
927             if (langContents[i] != nullptr) {
928                 xmlFree(langContents[i]);
929             }
930         }
931         cur = cur->next;
932     }
933     xmlFreeDoc(doc);
934 }
935 
SetRegion2DisplayName(const char * key,const char * value)936 void LocaleConfig::SetRegion2DisplayName(const char* key, const char* value)
937 {
938     std::lock_guard<std::mutex> regionDisplayLock(region2DisplayNameMutex);
939     region2DisplayName.insert(
940         std::make_pair<std::string, std::string>(key, value));
941 }
942 
SetLocale2DisplayName(const char * key,const char * value)943 void LocaleConfig::SetLocale2DisplayName(const char* key, const char* value)
944 {
945     std::lock_guard<std::mutex> localeDisplayLock(locale2DisplayNameMutex);
946     locale2DisplayName.insert(
947         std::make_pair<std::string, std::string>(key, value));
948 }
949 
ReadRegionData(const char * regionDataPath)950 void LocaleConfig::ReadRegionData(const char *regionDataPath)
951 {
952     xmlKeepBlanksDefault(0);
953     if (regionDataPath == nullptr) {
954         return;
955     }
956     xmlDocPtr doc = xmlParseFile(regionDataPath);
957     if (!doc) {
958         HILOG_INFO_I18N("can not open region data file");
959         return;
960     }
961     xmlNodePtr cur = xmlDocGetRootElement(doc);
962     if (cur) {
963         HILOG_INFO_I18N("cur pointer is true");
964     }
965     if (!cur || xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>(rootRegion))) {
966         xmlFreeDoc(doc);
967         HILOG_INFO_I18N("parse region data file failed");
968         return;
969     }
970     cur = cur->xmlChildrenNode;
971     while (cur != nullptr && !xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>(secondRootRegion))) {
972         xmlChar *regionContents[ELEMENT_NUM] = { 0 };
973         xmlNodePtr regionValue = cur->xmlChildrenNode;
974         bool xmlNodeNull = false;
975         for (size_t i = 0; i < ELEMENT_NUM && regionValue != nullptr; i++) {
976             regionContents[i] = xmlNodeGetContent(regionValue);
977             regionValue = regionValue->next;
978             if (regionContents[i] == nullptr) {
979                 xmlNodeNull = true;
980             }
981         }
982         if (!xmlNodeNull) {
983             // 0 represents langid index, 1 represents displayname index
984             const char* regionKey = reinterpret_cast<const char *>(regionContents[0]);
985             const char* regionVal = reinterpret_cast<const char *>(regionContents[1]);
986             SetRegion2DisplayName(regionKey, regionVal);
987         }
988         for (size_t i = 0; i < ELEMENT_NUM; i++) {
989             if (regionContents[i] != nullptr) {
990                 xmlFree(regionContents[i]);
991             }
992         }
993         cur = cur->next;
994     }
995     xmlFreeDoc(doc);
996 }
997 
GetDisplayLanguageWithDialect(const std::string & localeStr,const std::string & displayLocale)998 string LocaleConfig::GetDisplayLanguageWithDialect(const std::string &localeStr, const std::string &displayLocale)
999 {
1000     std::string finalLocale = ComputeLocale(displayLocale);
1001     if (finalLocale.empty()) {
1002         return "";
1003     }
1004     if (finalLocale.compare(currentDialectLocale) != 0) {
1005         std::string xmlPath = LANG_PATH + finalLocale + ".xml";
1006         locale2DisplayName.clear();
1007         ReadLangData(xmlPath.c_str());
1008         currentDialectLocale = finalLocale;
1009     }
1010     if (locale2DisplayName.find(localeStr) != locale2DisplayName.end()) {
1011         return locale2DisplayName.at(localeStr);
1012     }
1013     std::map<std::string, std::string> configs = {};
1014     LocaleInfo locale(localeStr, configs);
1015     std::string language = locale.GetLanguage();
1016     std::string scripts = locale.GetScript();
1017     std::string region = locale.GetRegion();
1018     if (scripts.length() != 0) {
1019         std::string languageAndScripts = language + "-" + scripts;
1020         if (locale2DisplayName.find(languageAndScripts) != locale2DisplayName.end()) {
1021             return locale2DisplayName.at(languageAndScripts);
1022         }
1023     }
1024     if (region.length() != 0) {
1025         std::string languageAndRegion = language + "-" + region;
1026         if (locale2DisplayName.find(languageAndRegion) != locale2DisplayName.end()) {
1027             return locale2DisplayName.at(languageAndRegion);
1028         }
1029     }
1030     if (locale2DisplayName.find(language) != locale2DisplayName.end()) {
1031         return locale2DisplayName.at(language);
1032     }
1033     return "";
1034 }
1035 
GetDisplayOverrideRegion(const std::string & region,const std::string & displayLocale)1036 string LocaleConfig::GetDisplayOverrideRegion(const std::string &region, const std::string &displayLocale)
1037 {
1038     UErrorCode status = U_ZERO_ERROR;
1039     icu::Locale originLocale;
1040     icu::UnicodeString displayRegion;
1041     if (displayLocale.compare(currentOverrideRegion) != 0) {
1042         std::string xmlPath = REGION_PATH + displayLocale + ".xml";
1043         region2DisplayName.clear();
1044         ReadRegionData(xmlPath.c_str());
1045         currentOverrideRegion = displayLocale;
1046     }
1047     if (region2DisplayName.find(region) != region2DisplayName.end()) {
1048         return region2DisplayName.at(region);
1049     } else {
1050         icu::Locale locale = icu::Locale::forLanguageTag(displayLocale, status);
1051         if (status != U_ZERO_ERROR) {
1052             return "";
1053         }
1054         if (IsValidRegion(region)) {
1055             icu::LocaleBuilder builder = icu::LocaleBuilder().setRegion(region);
1056             originLocale = builder.build(status);
1057         } else {
1058             originLocale = icu::Locale::forLanguageTag(region, status);
1059         }
1060         originLocale.getDisplayCountry(locale, displayRegion);
1061         std::string result;
1062         displayRegion.toUTF8String(result);
1063         return result;
1064     }
1065 }
1066 
GetDisplayRegion(const string & region,const string & displayLocale,bool sentenceCase)1067 string LocaleConfig::GetDisplayRegion(const string &region, const string &displayLocale, bool sentenceCase)
1068 {
1069     UErrorCode status = U_ZERO_ERROR;
1070     icu::Locale originLocale;
1071     if (IsValidRegion(region)) {
1072         icu::LocaleBuilder builder = icu::LocaleBuilder().setRegion(region);
1073         originLocale = builder.build(status);
1074     } else {
1075         originLocale = icu::Locale::forLanguageTag(region, status);
1076     }
1077     std::string country(originLocale.getCountry());
1078     if (country.length() == 0) {
1079         return PseudoLocalizationProcessor("");
1080     }
1081     if (status != U_ZERO_ERROR) {
1082         return PseudoLocalizationProcessor("");
1083     }
1084     icu::Locale locale = icu::Locale::forLanguageTag(displayLocale, status);
1085     if (status != U_ZERO_ERROR) {
1086         return PseudoLocalizationProcessor("");
1087     }
1088     icu::UnicodeString unistr;
1089     icu::UnicodeString displayRegion;
1090     std::string result;
1091     if (overrideSupportedRegions.find(displayLocale) != overrideSupportedRegions.end()) {
1092         result = GetDisplayOverrideRegion(region, displayLocale);
1093     } else {
1094         originLocale.getDisplayCountry(locale, displayRegion);
1095         displayRegion.toUTF8String(result);
1096     }
1097     if (sentenceCase) {
1098         char ch = static_cast<char>(toupper(result[0]));
1099         return PseudoLocalizationProcessor(result.replace(0, 1, 1, ch));
1100     }
1101     return PseudoLocalizationProcessor(result);
1102 }
1103 
IsRTL(const string & locale)1104 bool LocaleConfig::IsRTL(const string &locale)
1105 {
1106     icu::Locale curLocale(locale.c_str());
1107     return curLocale.isRightToLeft();
1108 }
1109 
parseExtension(const std::string & extension,std::map<std::string,std::string> & map)1110 void parseExtension(const std::string &extension, std::map<std::string, std::string> &map)
1111 {
1112     std::string pattern = "-..-";
1113     std::regex express(pattern);
1114 
1115     std::regex_token_iterator<std::string::const_iterator> begin1(extension.cbegin(), extension.cend(), express);
1116     std::regex_token_iterator<std::string::const_iterator> begin2(extension.cbegin(), extension.cend(), express, -1);
1117     begin2++;
1118     for (; begin1 != std::sregex_token_iterator() && begin2 != std::sregex_token_iterator(); begin1++, begin2++) {
1119         map.insert(std::pair<std::string, std::string>(begin1->str(), begin2->str()));
1120     }
1121 }
1122 
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)1123 void setExtension(std::string &extension, const std::string &tag, const std::set<string> &validValue,
1124     const std::map<std::string, std::string> &extensionMap,
1125     const std::map<std::string, std::string> &defaultExtensionMap)
1126 {
1127     std::string value;
1128     auto it = extensionMap.find(tag);
1129     if (it != extensionMap.end()) {
1130         value = it->second;
1131         if (validValue.find(value) == validValue.end()) {
1132             return;
1133         } else {
1134             extension += tag;
1135             extension += value;
1136         }
1137     } else {
1138         it = defaultExtensionMap.find(tag);
1139         if (it != defaultExtensionMap.end()) {
1140             value = it->second;
1141             if (validValue.find(value) == validValue.end()) {
1142                 return;
1143             } else {
1144                 extension += tag;
1145                 extension += value;
1146             }
1147         }
1148     }
1149 }
1150 
setOtherExtension(std::string & extension,std::map<std::string,std::string> & extensionMap,std::map<std::string,std::string> & defaultExtensionMap)1151 void setOtherExtension(std::string &extension, std::map<std::string, std::string> &extensionMap,
1152     std::map<std::string, std::string> &defaultExtensionMap)
1153 {
1154     std::set<std::string> tags;
1155     tags.insert("-ca-");
1156     tags.insert("-co-");
1157     tags.insert("-kn-");
1158     tags.insert("-kf-");
1159     tags.insert("-nu-");
1160     tags.insert("-hc-");
1161 
1162     for (auto it = tags.begin(); it != tags.end(); it++) {
1163         extensionMap.erase(*it);
1164         defaultExtensionMap.erase(*it);
1165     }
1166 
1167     for (auto it = defaultExtensionMap.begin(); it != defaultExtensionMap.end(); it++) {
1168         extensionMap.insert(std::pair<std::string, std::string>(it->first, it->second));
1169     }
1170 
1171     for (auto it = extensionMap.begin(); it != extensionMap.end(); it++) {
1172         extension += it->first;
1173         extension += it->second;
1174     }
1175 }
1176 
GetValidLocale(const std::string & localeTag)1177 std::string LocaleConfig::GetValidLocale(const std::string &localeTag)
1178 {
1179     std::string baseLocale = "";
1180     std::string extension = "";
1181     std::size_t found = localeTag.find("-u-");
1182     baseLocale = localeTag.substr(0, found);
1183     if (found != std::string::npos) {
1184         extension = localeTag.substr(found);
1185     }
1186     std::map<std::string, std::string> extensionMap;
1187     if (extension != "") {
1188         parseExtension(extension, extensionMap);
1189     }
1190 
1191     std::string systemLocaleTag = GetSystemLocale();
1192     std::string defaultExtension = "";
1193     found = systemLocaleTag.find("-u-");
1194     if (found != std::string::npos) {
1195         defaultExtension = systemLocaleTag.substr(found);
1196     }
1197     std::map<std::string, std::string> defaultExtensionMap;
1198     if (defaultExtension != "") {
1199         parseExtension(defaultExtension, defaultExtensionMap);
1200     }
1201 
1202     std::string ext = "";
1203     setExtension(ext, "-ca-", validCaTag, extensionMap, defaultExtensionMap);
1204     setExtension(ext, "-co-", validCoTag, extensionMap, defaultExtensionMap);
1205     setExtension(ext, "-kn-", validKnTag, extensionMap, defaultExtensionMap);
1206     setExtension(ext, "-kf-", validKfTag, extensionMap, defaultExtensionMap);
1207     setExtension(ext, "-nu-", validNuTag, extensionMap, defaultExtensionMap);
1208     setExtension(ext, "-hc-", validHcTag, extensionMap, defaultExtensionMap);
1209 
1210     std::string otherExt = "";
1211     setOtherExtension(otherExt, extensionMap, defaultExtensionMap);
1212     if (ext != "" || otherExt != "") {
1213         return baseLocale + "-u" + ext + otherExt;
1214     } else {
1215         return baseLocale;
1216     }
1217 }
1218 
IsEmpty24HourClock()1219 bool LocaleConfig::IsEmpty24HourClock()
1220 {
1221     std::string is24Hour = ReadSystemParameter(HOUR_KEY, CONFIG_LEN);
1222     return is24Hour.empty();
1223 }
1224 
Is24HourClock()1225 bool LocaleConfig::Is24HourClock()
1226 {
1227     std::string is24Hour = ReadSystemParameter(HOUR_KEY, CONFIG_LEN);
1228     if (is24Hour.empty()) {
1229         std::string systemLocale = GetSystemLocale();
1230         return Is24HourLocale(systemLocale);
1231     }
1232     if (is24Hour.compare("true") == 0) {
1233         return true;
1234     }
1235     return false;
1236 }
1237 
GetSystemHour()1238 std::string LocaleConfig::GetSystemHour()
1239 {
1240     std::string is24HourVal = ReadSystemParameter(HOUR_KEY, CONFIG_LEN);
1241     HILOG_INFO_I18N("GetSystemHour: read from system param:%{public}s.", is24HourVal.c_str());
1242     bool is24Hour = Is24HourClock();
1243     return is24Hour ? "true" : "false";
1244 }
1245 
Is24HourLocale(const std::string & systemLocale)1246 bool LocaleConfig::Is24HourLocale(const std::string& systemLocale)
1247 {
1248     static std::unordered_map<std::string, bool> is24HourLocaleMap;
1249     if (is24HourLocaleMap.find(systemLocale) != is24HourLocaleMap.end()) {
1250         return is24HourLocaleMap[systemLocale];
1251     }
1252     UErrorCode status = U_ZERO_ERROR;
1253     icu::Locale locale = icu::Locale::forLanguageTag(icu::StringPiece(systemLocale), status);
1254     if (U_FAILURE(status)) {
1255         HILOG_INFO_I18N("Is24HourLocale: %{public}s create locale failed", systemLocale.c_str());
1256         return false;
1257     }
1258 
1259     icu::UnicodeString formatPattern;
1260     icu::DateFormat* dateFormat = icu::DateFormat::createTimeInstance(icu::DateFormat::EStyle::kLong, locale);
1261     if (dateFormat == nullptr) {
1262         HILOG_INFO_I18N("Is24HourLocale: createTimeInstance failed");
1263         return false;
1264     }
1265     icu::SimpleDateFormat* simDateFormat = static_cast<icu::SimpleDateFormat*>(dateFormat);
1266     if (simDateFormat == nullptr) {
1267         HILOG_INFO_I18N("Is24HourLocale: failed to convert dateFormat");
1268         return false;
1269     }
1270     simDateFormat->toPattern(formatPattern);
1271     delete dateFormat;
1272     std::string pattern;
1273     formatPattern.toUTF8String(pattern);
1274     bool result = HasDesignator(pattern, 'H');
1275     is24HourLocaleMap[systemLocale] = result;
1276     return result;
1277 }
1278 
HasDesignator(const std::string & pattern,const char designator)1279 bool LocaleConfig::HasDesignator(const std::string& pattern, const char designator)
1280 {
1281     if (pattern.empty()) {
1282         HILOG_INFO_I18N("HasDesignator: pattern is empty");
1283         return false;
1284     }
1285     bool insideQuote = false;
1286     for (const auto& c : pattern) {
1287         if (c == '\'') {
1288             insideQuote = !insideQuote;
1289         } else if (!insideQuote) {
1290             if (c == designator) {
1291                 return true;
1292             }
1293         }
1294     }
1295     return false;
1296 }
1297 
GetUsingLocalDigit()1298 bool LocaleConfig::GetUsingLocalDigit()
1299 {
1300     std::string locale = GetSystemLocale();
1301     LocaleInfo localeInfo(locale);
1302     std::string language = localeInfo.GetLanguage();
1303     if (localDigitMap.find(language) == localDigitMap.end()) {
1304         return false;
1305     }
1306     std::string localNumberSystem = localDigitMap.at(language);
1307     if (localNumberSystem.compare(localeInfo.GetNumberingSystem()) != 0) {
1308         return false;
1309     }
1310     return true;
1311 }
1312 
GetBlockedLanguages()1313 std::unordered_set<std::string> LocaleConfig::GetBlockedLanguages()
1314 {
1315     return blockedLanguages;
1316 }
1317 
GetBlockedRegions()1318 std::unordered_set<std::string> LocaleConfig::GetBlockedRegions()
1319 {
1320     return blockedRegions;
1321 }
1322 
GetLanguageBlockedRegions()1323 std::unordered_set<std::string> LocaleConfig::GetLanguageBlockedRegions()
1324 {
1325     std::string systemLanguage = LocaleConfig::GetSystemLanguage();
1326     if (blockedLanguageRegions.find(systemLanguage) != blockedLanguageRegions.end()) {
1327         return blockedLanguageRegions[systemLanguage];
1328     }
1329     std::unordered_set<std::string> emptyResult;
1330     return emptyResult;
1331 }
1332 
SetSystemLanguage(const std::string & languageTag)1333 I18nErrorCode LocaleConfig::SetSystemLanguage(const std::string &languageTag)
1334 {
1335     if (!IsValidTag(languageTag)) {
1336         HILOG_ERROR_I18N("LocaleConfig::SetSystemLanguage %{public}s is not valid language tag.",
1337             languageTag.c_str());
1338         return I18nErrorCode::INVALID_LANGUAGE_TAG;
1339     }
1340     // save old language, reset system language to old language if update locale failed.
1341     std::string oldLanguageTag = GetSystemLanguage();
1342     if (SetParameter(LANGUAGE_KEY, languageTag.data()) != 0) {
1343         HILOG_ERROR_I18N("LocaleConfig::SetSystemLanguage update system language failed.");
1344         return I18nErrorCode::UPDATE_SYSTEM_LANGUAGE_FAILED;
1345     }
1346     std::string newLocaleTag = UpdateLanguageOfLocale(languageTag);
1347     if (SetSystemLocale(newLocaleTag) == I18nErrorCode::SUCCESS) {
1348         return I18nErrorCode::SUCCESS;
1349     }
1350     // reset system language to old language in case that system language is inconsist with system locale's lanuage.
1351     HILOG_ERROR_I18N("LocaleConfig::SetSystemLanguage update system locale failed.");
1352     SetParameter(LANGUAGE_KEY, oldLanguageTag.data());
1353     return I18nErrorCode::UPDATE_SYSTEM_LANGUAGE_FAILED;
1354 }
1355 
SetSystemRegion(const std::string & regionTag)1356 I18nErrorCode LocaleConfig::SetSystemRegion(const std::string &regionTag)
1357 {
1358     QueryUpgradeLocale();
1359     if (!IsValidRegion(regionTag)) {
1360         HILOG_ERROR_I18N("LocaleConfig::SetSystemRegion %{public}s is not valid region tag.", regionTag.c_str());
1361         return I18nErrorCode::INVALID_REGION_TAG;
1362     }
1363     return SetSystemLocale(UpdateRegionOfLocale(regionTag));
1364 }
1365 
QueryUpgradeLocale()1366 void LocaleConfig::QueryUpgradeLocale()
1367 {
1368     std::string upgradeLocale = ReadSystemParameter(UPGRADE_LOCALE_KEY, CONFIG_LEN);
1369     if (!upgradeLocale.empty()) {
1370         HILOG_ERROR_I18N("LocaleConfig::QueryUpgradeLocale: upgrade locale is %{public}s.", upgradeLocale.c_str());
1371     }
1372 }
1373 
SetSystemLocale(const std::string & localeTag)1374 I18nErrorCode LocaleConfig::SetSystemLocale(const std::string &localeTag)
1375 {
1376     if (!IsValidTag(localeTag)) {
1377         HILOG_ERROR_I18N("LocaleConfig::SetSystemLocale %{public}s is not a valid locale tag.", localeTag.c_str());
1378         return I18nErrorCode::INVALID_LOCALE_TAG;
1379     }
1380     if (SetParameter(LOCALE_KEY, localeTag.data()) != 0) {
1381         return I18nErrorCode::UPDATE_SYSTEM_LOCALE_FAILED;
1382     }
1383 #ifdef SUPPORT_GRAPHICS
1384     UpdateConfiguration(AAFwk::GlobalConfigurationKey::SYSTEM_LANGUAGE, localeTag);
1385     return PublishCommonEvent(EventFwk::CommonEventSupport::COMMON_EVENT_LOCALE_CHANGED);
1386 #else
1387     return I18nErrorCode::SUCCESS;
1388 #endif
1389 }
1390 
IsValid24HourClockValue(const std::string & tag)1391 bool LocaleConfig::IsValid24HourClockValue(const std::string &tag)
1392 {
1393     if (tag.compare("true") == 0 || tag.compare("false") == 0 || tag.length() == 0) {
1394         return true;
1395     }
1396     return false;
1397 }
1398 
Set24HourClock(const std::string & option)1399 I18nErrorCode LocaleConfig::Set24HourClock(const std::string &option)
1400 {
1401     if (!IsValid24HourClockValue(option)) {
1402         HILOG_ERROR_I18N("LocaleConfig::Set24HourClock invalid 24 Hour clock tag: %{public}s", option.c_str());
1403         return I18nErrorCode::INVALID_24_HOUR_CLOCK_TAG;
1404     }
1405     if (SetParameter(HOUR_KEY, option.data()) != 0) {
1406         HILOG_ERROR_I18N("LocaleConfig::Set24HourClock update 24 hour clock failed with option=%{public}s",
1407             option.c_str());
1408         return I18nErrorCode::UPDATE_24_HOUR_CLOCK_FAILED;
1409     }
1410 #ifdef SUPPORT_GRAPHICS
1411     UpdateConfiguration(AAFwk::GlobalConfigurationKey::SYSTEM_HOUR, option);
1412     return PublishCommonEvent(EventFwk::CommonEventSupport::COMMON_EVENT_TIME_CHANGED);
1413 #else
1414     return I18nErrorCode::SUCCESS;
1415 #endif
1416 }
1417 
SetUsingLocalDigit(bool flag)1418 I18nErrorCode LocaleConfig::SetUsingLocalDigit(bool flag)
1419 {
1420     // check whether current language support local digit.
1421     std::string localeTag = GetSystemLocale();
1422     std::string languageTag = localeTag.substr(0, 2); // obtain 2 length language code.
1423     auto it = localDigitMap.find(languageTag);
1424     if (it == localDigitMap.end()) {
1425         HILOG_ERROR_I18N("LocaleConfig::SetUsingLocalDigit current system doesn't support set local digit");
1426         return I18nErrorCode::UPDATE_LOCAL_DIGIT_FAILED;
1427     }
1428     // update system locale.
1429     return SetSystemLocale(UpdateNumberSystemOfLocale(it->second, flag));
1430 }
1431 
UpdateNumberSystemOfLocale(const std::string & localDigitTag,bool flag)1432 std::string LocaleConfig::UpdateNumberSystemOfLocale(const std::string &localDigitTag, bool flag)
1433 {
1434     if (flag) {
1435         // add local digit tag to number system param of locale
1436         return AddLocalDigitToLocale(localDigitTag);
1437     }
1438     // remove local digit tag to number system param of locale
1439     return RemoveLocalDigitFromLocale(localDigitTag);
1440 }
1441 
AddLocalDigitToLocale(const std::string & localDigitTag)1442 std::string LocaleConfig::AddLocalDigitToLocale(const std::string &localDigitTag)
1443 {
1444     std::string localeTag = GetSystemLocale();
1445     // Case: no extend param, add '-u-' and number system tag.
1446     if (localeTag.find("-u-") == std::string::npos) {
1447         localeTag += "-u" + std::string(NUMBER_SYSTEM_KEY) + localDigitTag;
1448         return localeTag;
1449     }
1450     // Case: has extend param but doesn't hava number system param, add number system tag.
1451     if (localeTag.find(NUMBER_SYSTEM_KEY) == std::string::npos) {
1452         localeTag += std::string(NUMBER_SYSTEM_KEY) + localDigitTag;
1453         return localeTag;
1454     }
1455     // Case: has number system param, replace local digit tag to localDigitTag.
1456     LocaleInfo localeInfo(localeTag);
1457     std::string oldNumberSystem = localeInfo.GetNumberingSystem();
1458     localeTag.replace(localeTag.find(oldNumberSystem), oldNumberSystem.length(), localDigitTag);
1459     return localeTag;
1460 }
1461 
RemoveLocalDigitFromLocale(const std::string & localDigitTag)1462 std::string LocaleConfig::RemoveLocalDigitFromLocale(const std::string &localDigitTag)
1463 {
1464     // remove number system tag from locale
1465     std::string localeTag = GetSystemLocale();
1466     std::string numberSystemTag = NUMBER_SYSTEM_KEY + localDigitTag;
1467     size_t pos = localeTag.find(numberSystemTag);
1468     if (pos != std::string::npos) {
1469         localeTag.replace(pos, numberSystemTag.length(), "");
1470     }
1471     // remove "-u" if localeTag ends with "-u"
1472     size_t uLength = 2;
1473     if (localeTag.find("-u") == (localeTag.length() - uLength)) {
1474         localeTag.resize(localeTag.length() - uLength);
1475     }
1476     return localeTag;
1477 }
1478 
1479 #ifdef SUPPORT_GRAPHICS
UpdateConfiguration(const char * key,const std::string & value)1480 void LocaleConfig::UpdateConfiguration(const char *key, const std::string &value)
1481 {
1482     AppExecFwk::Configuration configuration;
1483     configuration.AddItem(key, value);
1484     auto appMgrClient = std::make_unique<AppExecFwk::AppMgrClient>();
1485     appMgrClient->UpdateConfiguration(configuration);
1486     HILOG_INFO_I18N("LocaleConfig::UpdateLanguageConfiguration update configuration finished.");
1487 }
1488 
PublishCommonEvent(const std::string & eventType)1489 I18nErrorCode LocaleConfig::PublishCommonEvent(const std::string &eventType)
1490 {
1491     OHOS::AAFwk::Want localeChangeWant;
1492     localeChangeWant.SetAction(eventType);
1493     OHOS::EventFwk::CommonEventData event(localeChangeWant);
1494     if (EventFwk::CommonEventSupport::COMMON_EVENT_TIME_CHANGED.compare(eventType) == 0) {
1495         event.SetData(HOUR_EVENT_DATA);
1496     }
1497     if (!OHOS::EventFwk::CommonEventManager::PublishCommonEvent(event)) {
1498         HILOG_ERROR_I18N("LocaleConfig::PublishCommonEvent Failed to Publish event %{public}s",
1499             localeChangeWant.GetAction().c_str());
1500         return I18nErrorCode::PUBLISH_COMMON_EVENT_FAILED;
1501     }
1502     HILOG_INFO_I18N("LocaleConfig::PublishCommonEvent publish event finished.");
1503     return I18nErrorCode::SUCCESS;
1504 }
1505 #endif
1506 
UpdateLanguageOfLocale(const std::string & languageTag)1507 std::string LocaleConfig::UpdateLanguageOfLocale(const std::string &languageTag)
1508 {
1509     // Compute language and script part from languageTag.
1510     UErrorCode status = U_ZERO_ERROR;
1511     icu::Locale languageLocale = icu::Locale::forLanguageTag(languageTag.c_str(), status);
1512     if (U_FAILURE(status)) {
1513         HILOG_ERROR_I18N("LocaleConfig::UpdateLanguageOfLocale init icu Locale for language %{public}s failed.",
1514             languageTag.c_str());
1515         return "";
1516     }
1517     std::string langTag = languageLocale.getLanguage();
1518     std::string scriptTag = languageLocale.getScript();
1519     // Compute region and extend param part from current system locale.
1520     std::string systemLocaleTag = GetSystemLocale();
1521     icu::Locale systemLocale = icu::Locale::forLanguageTag(systemLocaleTag.c_str(), status);
1522     if (U_FAILURE(status)) {
1523         HILOG_ERROR_I18N("LocaleConfig::UpdateSystemLocale init icu Locale for locale %{public}s failed.",
1524             systemLocaleTag.c_str());
1525         return "";
1526     }
1527     std::string regionTag = systemLocale.getCountry();
1528     std::string extendParamTag;
1529     size_t pos = systemLocaleTag.find("-u-");
1530     if (pos != std::string::npos) {
1531         extendParamTag = systemLocaleTag.substr(pos);
1532     }
1533     // Combine above elements.
1534     return CreateLocale(langTag, scriptTag, regionTag, extendParamTag);
1535 }
1536 
CreateLocale(const std::string & languageTag,const std::string & scriptTag,const std::string & regionTag,const std::string & extendParamTag)1537 std::string LocaleConfig::CreateLocale(const std::string &languageTag, const std::string &scriptTag,
1538     const std::string &regionTag, const std::string &extendParamTag)
1539 {
1540     // combine language, script, region and extend param with '-'
1541     std::string localeTag = languageTag;
1542     std::string splitor = "-";
1543     if (scriptTag.length() > 0) {
1544         localeTag += splitor + scriptTag;
1545     }
1546     if (regionTag.length() > 0) {
1547         localeTag += splitor + regionTag;
1548     }
1549     if (extendParamTag.length() > 0) {
1550         localeTag += extendParamTag;
1551     }
1552     return localeTag;
1553 }
1554 
UpdateRegionOfLocale(const std::string & regionTag)1555 std::string LocaleConfig::UpdateRegionOfLocale(const std::string &regionTag)
1556 {
1557     std::string localeTag = GetSystemLocale();
1558     // if current system locale is null, contruct a locale from region tag.
1559     if (localeTag.length() == 0) {
1560         return CreateLocaleFromRegion(regionTag);
1561     }
1562     // combine locale with origin locale's language and script with regionTag.
1563     UErrorCode status = U_ZERO_ERROR;
1564     const icu::Locale origin = icu::Locale::forLanguageTag(localeTag, status);
1565     if (U_FAILURE(status)) {
1566         HILOG_ERROR_I18N("LocaleConfig::UpdateRegionOfLocale init origin locale failed.");
1567         return "";
1568     }
1569     icu::LocaleBuilder builder = icu::LocaleBuilder().setLanguage(origin.getLanguage()).
1570         setScript(origin.getScript()).setRegion(regionTag);
1571     icu::Locale temp = builder.setExtension('u', "").build(status);
1572     string ret = temp.toLanguageTag<string>(status);
1573     if (U_FAILURE(status)) {
1574         HILOG_ERROR_I18N("LocaleConfig::UpdateRegionOfLocale obtain new locale's tag failed.");
1575         return "";
1576     }
1577     return ret;
1578 }
1579 
CreateLocaleFromRegion(const std::string & regionTag)1580 std::string LocaleConfig::CreateLocaleFromRegion(const std::string &regionTag)
1581 {
1582     // fill locale with icu
1583     icu::Locale locale("", regionTag.c_str());
1584     UErrorCode status = U_ZERO_ERROR;
1585     locale.addLikelySubtags(status);
1586     if (U_FAILURE(status)) {
1587         HILOG_ERROR_I18N("LocaleConfig::CreateLocaleFromRegion init new locale failed.");
1588         return "";
1589     }
1590     std::string localeTag = locale.toLanguageTag<string>(status);
1591     if (U_FAILURE(status)) {
1592         HILOG_ERROR_I18N("LocaleConfig::CreateLocaleFromRegion obtain new locale's tag failed.");
1593         return "";
1594     }
1595     return localeTag;
1596 }
1597 
GetSimplifiedLanguage(const std::string & languageTag,int32_t & code)1598 std::string LocaleConfig::GetSimplifiedLanguage(const std::string& languageTag, int32_t &code)
1599 {
1600     std::string simplifiedLanguage = "";
1601     if (IsValidTag(languageTag)) {
1602         LocaleInfo localeInfo(languageTag);
1603         simplifiedLanguage = localeInfo.Minimize();
1604     } else {
1605         code = 1;
1606     }
1607     return simplifiedLanguage;
1608 }
1609 
GetSimplifiedSystemLanguage()1610 std::string LocaleConfig::GetSimplifiedSystemLanguage()
1611 {
1612     std::string locale = GetSystemLanguage();
1613     LocaleInfo localeInfo(locale);
1614     LocaleInfo localeInfoMax(localeInfo.Maximize());
1615     std::string language = localeInfoMax.GetLanguage();
1616     language = language + '-' + localeInfoMax.GetScript();
1617     if (dialectLanguages.find(language) != dialectLanguages.end()) {
1618         std::string systemRegion = localeInfo.GetRegion();
1619         if (!systemRegion.empty() && language.compare("en-Latn") != 0) {
1620             locale = language + '-' + systemRegion;
1621         } else {
1622             locale = GetSystemLocale();
1623         }
1624         LocaleInfo* requestLocale = new(std::nothrow) LocaleInfo(locale);
1625         if (requestLocale == nullptr) {
1626             HILOG_ERROR_I18N("GetSimplifiedLanguage: %{public}s failed to construct LocaleInfo.", locale.c_str());
1627             return "";
1628         }
1629         std::vector<LocaleInfo*> candidateLocales;
1630         for (auto& candidate : dialectLanguages[language]) {
1631             LocaleInfo* candidateInfo = new LocaleInfo(candidate);
1632             if (candidateInfo == nullptr) {
1633                 HILOG_ERROR_I18N("GetSimplifiedLanguage: %{public}s failed to construct LocaleInfo.",
1634                     candidate.c_str());
1635                 continue;
1636             }
1637             candidateLocales.push_back(candidateInfo);
1638         }
1639         locale = LocaleMatcher::GetBestMatchedLocale(requestLocale, candidateLocales);
1640 
1641         for (LocaleInfo* candidateInfo : candidateLocales) {
1642             delete candidateInfo;
1643             candidateInfo = nullptr;
1644         }
1645         delete requestLocale;
1646         requestLocale = nullptr;
1647     }
1648     LocaleInfo simplifiedLocale(locale);
1649     std::string ret = simplifiedLocale.Minimize();
1650     auto iter = resourceIdMap.find(ret);
1651     if (iter != resourceIdMap.end()) {
1652         ret = iter->second;
1653     }
1654     return ret;
1655 }
1656 } // namespace I18n
1657 } // namespace Global
1658 } // namespace OHOS
1659