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 ®ion)
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 ®ion)
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 ®ion)
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> ®ions = 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> ®ions = 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 ®ion, 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 ®ion, 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 ®ionTag)
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 ®ionTag, 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 ®ionTag)
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 ®ionTag)
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