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