19596a2c1Sopenharmony_ci/*
29596a2c1Sopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
39596a2c1Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
49596a2c1Sopenharmony_ci * you may not use this file except in compliance with the License.
59596a2c1Sopenharmony_ci * You may obtain a copy of the License at
69596a2c1Sopenharmony_ci *
79596a2c1Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
89596a2c1Sopenharmony_ci *
99596a2c1Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
109596a2c1Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
119596a2c1Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
129596a2c1Sopenharmony_ci * See the License for the specific language governing permissions and
139596a2c1Sopenharmony_ci * limitations under the License.
149596a2c1Sopenharmony_ci */
159596a2c1Sopenharmony_ci#include <regex>
169596a2c1Sopenharmony_ci#include "accesstoken_kit.h"
179596a2c1Sopenharmony_ci#ifdef SUPPORT_GRAPHICS
189596a2c1Sopenharmony_ci#include "app_mgr_client.h"
199596a2c1Sopenharmony_ci#include "ability_manager_client.h"
209596a2c1Sopenharmony_ci#include <common_event_manager.h>
219596a2c1Sopenharmony_ci#include <common_event_publish_info.h>
229596a2c1Sopenharmony_ci#include <common_event_support.h>
239596a2c1Sopenharmony_ci#endif
249596a2c1Sopenharmony_ci#include <cctype>
259596a2c1Sopenharmony_ci#include "config_policy_utils.h"
269596a2c1Sopenharmony_ci#include "i18n_hilog.h"
279596a2c1Sopenharmony_ci#include "ipc_skeleton.h"
289596a2c1Sopenharmony_ci#include "libxml/parser.h"
299596a2c1Sopenharmony_ci#include "locale_info.h"
309596a2c1Sopenharmony_ci#include "multi_users.h"
319596a2c1Sopenharmony_ci#include "unicode/localebuilder.h"
329596a2c1Sopenharmony_ci#include "unicode/locdspnm.h"
339596a2c1Sopenharmony_ci#include "unicode/locid.h"
349596a2c1Sopenharmony_ci#include "unicode/smpdtfmt.h"
359596a2c1Sopenharmony_ci#include "ohos/init_data.h"
369596a2c1Sopenharmony_ci#include "parameter.h"
379596a2c1Sopenharmony_ci#include "securec.h"
389596a2c1Sopenharmony_ci#include "string_ex.h"
399596a2c1Sopenharmony_ci#include "ucase.h"
409596a2c1Sopenharmony_ci#include "ulocimp.h"
419596a2c1Sopenharmony_ci#include "unicode/unistr.h"
429596a2c1Sopenharmony_ci#include "ureslocs.h"
439596a2c1Sopenharmony_ci#include "unicode/ustring.h"
449596a2c1Sopenharmony_ci#include "ustr_imp.h"
459596a2c1Sopenharmony_ci#include "utils.h"
469596a2c1Sopenharmony_ci#include "tokenid_kit.h"
479596a2c1Sopenharmony_ci#include "locale_config.h"
489596a2c1Sopenharmony_ci
499596a2c1Sopenharmony_cinamespace OHOS {
509596a2c1Sopenharmony_cinamespace Global {
519596a2c1Sopenharmony_cinamespace I18n {
529596a2c1Sopenharmony_ciusing namespace std;
539596a2c1Sopenharmony_ciconst char *LocaleConfig::LANGUAGE_KEY = "persist.global.language";
549596a2c1Sopenharmony_ciconst char *LocaleConfig::LOCALE_KEY = "persist.global.locale";
559596a2c1Sopenharmony_ciconst char *LocaleConfig::HOUR_KEY = "persist.global.is24Hour";
569596a2c1Sopenharmony_ciconst char *LocaleConfig::DEFAULT_LOCALE_KEY = "const.global.locale";
579596a2c1Sopenharmony_ciconst char *LocaleConfig::DEFAULT_LANGUAGE_KEY = "const.global.language";
589596a2c1Sopenharmony_ciconst char *LocaleConfig::DEFAULT_REGION_KEY = "const.global.region";
599596a2c1Sopenharmony_ciconst char *LocaleConfig::SIM_COUNTRY_CODE_KEY = "telephony.sim.countryCode0";
609596a2c1Sopenharmony_ciconst char *LocaleConfig::SUPPORTED_LOCALES_NAME = "supported_locales";
619596a2c1Sopenharmony_ciconst char *LocaleConfig::REGIONS_LANGUAGES_PATH = "etc/xml/i18n_param_config.xml";
629596a2c1Sopenharmony_ciconst char *LocaleConfig::REGIONS_LANGUAGES_NAME = "i18n_param_config";
639596a2c1Sopenharmony_ciconst char *LocaleConfig::SUPPORTED_REGIONS_NAME = "supported_regions";
649596a2c1Sopenharmony_ciconst char *LocaleConfig::WHITE_LANGUAGES_NAME = "white_languages";
659596a2c1Sopenharmony_ciconst char *LocaleConfig::FORBIDDEN_LANGUAGES_NAME = "forbidden_languages";
669596a2c1Sopenharmony_ciconst char *LocaleConfig::FORBIDDEN_REGIONS_NAME = "forbidden_regions";
679596a2c1Sopenharmony_ciconst char *LocaleConfig::SUPPORTED_LOCALES_PATH = "/system/usr/ohos_locale_config/supported_locales.xml";
689596a2c1Sopenharmony_ciconst char *LocaleConfig::SUPPORT_LOCALES_PATH = "/etc/ohos_lang_config/supported_locales.xml";
699596a2c1Sopenharmony_ciconst char *LocaleConfig::SUPPORT_LOCALES_NAME = "supported_locales";
709596a2c1Sopenharmony_ciconst char *LocaleConfig::DIALECT_LANGS_PATH = "/system/usr/ohos_locale_config/dialect_languages.xml";
719596a2c1Sopenharmony_ciconst char *LocaleConfig::DIALECT_LANGS_NAME = "dialect_langs";
729596a2c1Sopenharmony_ciconst char *LocaleConfig::OVERRIDE_SUPPORTED_REGIONS_NAME = "supported_regions";
739596a2c1Sopenharmony_ciconst char *LocaleConfig::OVERRIDE_SUPPORTED_REGIONS_PATH =
749596a2c1Sopenharmony_ci    "/system/usr/ohos_locale_config/region/supported_regions.xml";
759596a2c1Sopenharmony_ciconst char *LocaleConfig::DEFAULT_LOCALE = "en-Latn";
769596a2c1Sopenharmony_ciconst char *LocaleConfig::supportLocalesTag = "supported_locales";
779596a2c1Sopenharmony_ciconst char *LocaleConfig::LANG_PATH = "/etc/ohos_lang_config/";
789596a2c1Sopenharmony_ciconst char *LocaleConfig::REGION_PATH = "/system/usr/ohos_locale_config/region/";
799596a2c1Sopenharmony_ciconst char *LocaleConfig::rootTag = "languages";
809596a2c1Sopenharmony_ciconst char *LocaleConfig::secondRootTag = "lang";
819596a2c1Sopenharmony_ciconst char *LocaleConfig::rootRegion = "regions";
829596a2c1Sopenharmony_ciconst char *LocaleConfig::secondRootRegion = "region";
839596a2c1Sopenharmony_ciconst char *LocaleConfig::NUMBER_SYSTEM_KEY = "-nu-";
849596a2c1Sopenharmony_ciunordered_set<string> LocaleConfig::supportedLocales;
859596a2c1Sopenharmony_ciunordered_set<string> LocaleConfig::supportLocales;
869596a2c1Sopenharmony_ciunordered_set<string> LocaleConfig::supportedRegions;
879596a2c1Sopenharmony_ciunordered_set<string> LocaleConfig::overrideSupportedRegions;
889596a2c1Sopenharmony_ciunordered_set<string> LocaleConfig::dialectLang;
899596a2c1Sopenharmony_ciunordered_set<string> LocaleConfig::blockedLanguages;
909596a2c1Sopenharmony_ciunordered_set<string> LocaleConfig::blockedRegions;
919596a2c1Sopenharmony_ciunordered_map<string, unordered_set<string>> LocaleConfig::blockedLanguageRegions;
929596a2c1Sopenharmony_ciunordered_set<string> LocaleConfig::whiteLanguages;
939596a2c1Sopenharmony_cistd::set<std::string> LocaleConfig::extendWhiteLanguageList;
949596a2c1Sopenharmony_ciunordered_map<string, string> LocaleConfig::dialectMap {
959596a2c1Sopenharmony_ci    { "es-Latn-419", "es-Latn-419" },
969596a2c1Sopenharmony_ci    { "es-Latn-BO", "es-Latn-419" },
979596a2c1Sopenharmony_ci    { "es-Latn-BR", "es-Latn-419" },
989596a2c1Sopenharmony_ci    { "es-Latn-BZ", "es-Latn-419" },
999596a2c1Sopenharmony_ci    { "es-Latn-CL", "es-Latn-419" },
1009596a2c1Sopenharmony_ci    { "es-Latn-CO", "es-Latn-419" },
1019596a2c1Sopenharmony_ci    { "es-Latn-CR", "es-Latn-419" },
1029596a2c1Sopenharmony_ci    { "es-Latn-CU", "es-Latn-419" },
1039596a2c1Sopenharmony_ci    { "es-Latn-DO", "es-Latn-419" },
1049596a2c1Sopenharmony_ci    { "es-Latn-EC", "es-Latn-419" },
1059596a2c1Sopenharmony_ci    { "es-Latn-GT", "es-Latn-419" },
1069596a2c1Sopenharmony_ci    { "es-Latn-HN", "es-Latn-419" },
1079596a2c1Sopenharmony_ci    { "es-Latn-MX", "es-Latn-419" },
1089596a2c1Sopenharmony_ci    { "es-Latn-NI", "es-Latn-419" },
1099596a2c1Sopenharmony_ci    { "es-Latn-PA", "es-Latn-419" },
1109596a2c1Sopenharmony_ci    { "es-Latn-PE", "es-Latn-419" },
1119596a2c1Sopenharmony_ci    { "es-Latn-PR", "es-Latn-419" },
1129596a2c1Sopenharmony_ci    { "es-Latn-PY", "es-Latn-419" },
1139596a2c1Sopenharmony_ci    { "es-Latn-SV", "es-Latn-419" },
1149596a2c1Sopenharmony_ci    { "es-Latn-US", "es-Latn-419" },
1159596a2c1Sopenharmony_ci    { "es-Latn-UY", "es-Latn-419" },
1169596a2c1Sopenharmony_ci    { "es-Latn-VE", "es-Latn-419" },
1179596a2c1Sopenharmony_ci    { "pt-Latn-PT", "pt-Latn-PT" },
1189596a2c1Sopenharmony_ci    { "en-Latn-US", "en-Latn-US" }
1199596a2c1Sopenharmony_ci};
1209596a2c1Sopenharmony_ci
1219596a2c1Sopenharmony_ciunordered_map<string, string> LocaleConfig::localDigitMap {
1229596a2c1Sopenharmony_ci    { "ar", "arab" },
1239596a2c1Sopenharmony_ci    { "as", "beng" },
1249596a2c1Sopenharmony_ci    { "bn", "beng" },
1259596a2c1Sopenharmony_ci    { "fa", "arabext" },
1269596a2c1Sopenharmony_ci    { "mr", "deva" },
1279596a2c1Sopenharmony_ci    { "my", "mymr" },
1289596a2c1Sopenharmony_ci    { "ne", "deva" },
1299596a2c1Sopenharmony_ci    { "ur", "latn" }
1309596a2c1Sopenharmony_ci};
1319596a2c1Sopenharmony_ci
1329596a2c1Sopenharmony_cistd::map<std::string, std::string> LocaleConfig::supportedDialectLocales;
1339596a2c1Sopenharmony_cistd::map<string, string> LocaleConfig::locale2DisplayName {};
1349596a2c1Sopenharmony_cistd::map<string, string> LocaleConfig::region2DisplayName {};
1359596a2c1Sopenharmony_cistd::string LocaleConfig::currentDialectLocale = "";
1369596a2c1Sopenharmony_cistd::string LocaleConfig::currentOverrideRegion = "";
1379596a2c1Sopenharmony_cistd::mutex LocaleConfig::dialectLocaleMutex;
1389596a2c1Sopenharmony_cistd::mutex LocaleConfig::region2DisplayNameMutex;
1399596a2c1Sopenharmony_cistd::mutex LocaleConfig::locale2DisplayNameMutex;
1409596a2c1Sopenharmony_ci
1419596a2c1Sopenharmony_ciset<std::string> LocaleConfig::validCaTag {
1429596a2c1Sopenharmony_ci    "buddhist",
1439596a2c1Sopenharmony_ci    "chinese",
1449596a2c1Sopenharmony_ci    "coptic",
1459596a2c1Sopenharmony_ci    "dangi",
1469596a2c1Sopenharmony_ci    "ethioaa",
1479596a2c1Sopenharmony_ci    "ethiopic",
1489596a2c1Sopenharmony_ci    "gregory",
1499596a2c1Sopenharmony_ci    "hebrew",
1509596a2c1Sopenharmony_ci    "indian",
1519596a2c1Sopenharmony_ci    "islamic",
1529596a2c1Sopenharmony_ci    "islamic-umalqura",
1539596a2c1Sopenharmony_ci    "islamic-tbla",
1549596a2c1Sopenharmony_ci    "islamic-civil",
1559596a2c1Sopenharmony_ci    "islamic-rgsa",
1569596a2c1Sopenharmony_ci    "iso8601",
1579596a2c1Sopenharmony_ci    "japanese",
1589596a2c1Sopenharmony_ci    "persian",
1599596a2c1Sopenharmony_ci    "roc",
1609596a2c1Sopenharmony_ci    "islamicc",
1619596a2c1Sopenharmony_ci};
1629596a2c1Sopenharmony_ciset<std::string> LocaleConfig::validCoTag {
1639596a2c1Sopenharmony_ci    "big5han",
1649596a2c1Sopenharmony_ci    "compat",
1659596a2c1Sopenharmony_ci    "dict",
1669596a2c1Sopenharmony_ci    "direct",
1679596a2c1Sopenharmony_ci    "ducet",
1689596a2c1Sopenharmony_ci    "eor",
1699596a2c1Sopenharmony_ci    "gb2312",
1709596a2c1Sopenharmony_ci    "phonebk",
1719596a2c1Sopenharmony_ci    "phonetic",
1729596a2c1Sopenharmony_ci    "pinyin",
1739596a2c1Sopenharmony_ci    "reformed",
1749596a2c1Sopenharmony_ci    "searchjl",
1759596a2c1Sopenharmony_ci    "stroke",
1769596a2c1Sopenharmony_ci    "trad",
1779596a2c1Sopenharmony_ci    "unihan",
1789596a2c1Sopenharmony_ci    "zhuyin",
1799596a2c1Sopenharmony_ci};
1809596a2c1Sopenharmony_ciset<std::string> LocaleConfig::validKnTag {
1819596a2c1Sopenharmony_ci    "true",
1829596a2c1Sopenharmony_ci    "false",
1839596a2c1Sopenharmony_ci};
1849596a2c1Sopenharmony_ciset<std::string> LocaleConfig::validKfTag {
1859596a2c1Sopenharmony_ci    "upper",
1869596a2c1Sopenharmony_ci    "lower",
1879596a2c1Sopenharmony_ci    "false",
1889596a2c1Sopenharmony_ci};
1899596a2c1Sopenharmony_ciset<std::string> LocaleConfig::validNuTag {
1909596a2c1Sopenharmony_ci    "adlm", "ahom", "arab", "arabext", "bali", "beng",
1919596a2c1Sopenharmony_ci    "bhks", "brah", "cakm", "cham", "deva", "diak",
1929596a2c1Sopenharmony_ci    "fullwide", "gong", "gonm", "gujr", "guru", "hanidec",
1939596a2c1Sopenharmony_ci    "hmng", "hmnp", "java", "kali", "khmr", "knda",
1949596a2c1Sopenharmony_ci    "lana", "lanatham", "laoo", "latn", "lepc", "limb",
1959596a2c1Sopenharmony_ci    "mathbold", "mathdbl", "mathmono", "mathsanb", "mathsans", "mlym",
1969596a2c1Sopenharmony_ci    "modi", "mong", "mroo", "mtei", "mymr", "mymrshan",
1979596a2c1Sopenharmony_ci    "mymrtlng", "newa", "nkoo", "olck", "orya", "osma",
1989596a2c1Sopenharmony_ci    "rohg", "saur", "segment", "shrd", "sind", "sinh",
1999596a2c1Sopenharmony_ci    "sora", "sund", "takr", "talu", "tamldec", "telu",
2009596a2c1Sopenharmony_ci    "thai", "tibt", "tirh", "vaii", "wara", "wcho",
2019596a2c1Sopenharmony_ci};
2029596a2c1Sopenharmony_ciset<std::string> LocaleConfig::validHcTag {
2039596a2c1Sopenharmony_ci    "h12",
2049596a2c1Sopenharmony_ci    "h23",
2059596a2c1Sopenharmony_ci    "h11",
2069596a2c1Sopenharmony_ci    "h24",
2079596a2c1Sopenharmony_ci};
2089596a2c1Sopenharmony_ci
2099596a2c1Sopenharmony_cistatic unordered_map<string, string> g_languageMap = {
2109596a2c1Sopenharmony_ci    { "zh-Hans", "zh-Hans" },
2119596a2c1Sopenharmony_ci    { "zh-Hant-HK", "zh-Hant-HK" },
2129596a2c1Sopenharmony_ci    { "zh-Hant", "zh-Hant" },
2139596a2c1Sopenharmony_ci    { "my-Qaag", "my-Qaag" },
2149596a2c1Sopenharmony_ci    { "es-Latn-419", "es-419" },
2159596a2c1Sopenharmony_ci    { "es-Latn-US", "es-419" },
2169596a2c1Sopenharmony_ci    { "az-Latn", "az-Latn" },
2179596a2c1Sopenharmony_ci    { "bs-Latn", "bs-Latn" },
2189596a2c1Sopenharmony_ci    { "en-Latn-US", "en" },
2199596a2c1Sopenharmony_ci    { "en-Qaag", "en-Qaag" },
2209596a2c1Sopenharmony_ci    { "uz-Latn", "uz-Latn" },
2219596a2c1Sopenharmony_ci    { "sr-Latn", "sr-Latn" },
2229596a2c1Sopenharmony_ci    { "jv-Latn", "jv-Latn" },
2239596a2c1Sopenharmony_ci    { "pt-Latn-BR", "pt-BR" },
2249596a2c1Sopenharmony_ci    { "pa-Guru", "pa-Guru" },
2259596a2c1Sopenharmony_ci    { "mai-Deva", "mai-Deva" }
2269596a2c1Sopenharmony_ci};
2279596a2c1Sopenharmony_ci
2289596a2c1Sopenharmony_cistring Adjust(const string &origin)
2299596a2c1Sopenharmony_ci{
2309596a2c1Sopenharmony_ci    auto iter = g_languageMap.find(origin);
2319596a2c1Sopenharmony_ci    if (iter != g_languageMap.end()) {
2329596a2c1Sopenharmony_ci        return iter->second;
2339596a2c1Sopenharmony_ci    }
2349596a2c1Sopenharmony_ci    for (iter = g_languageMap.begin(); iter != g_languageMap.end(); ++iter) {
2359596a2c1Sopenharmony_ci        string key = iter->first;
2369596a2c1Sopenharmony_ci        if (!origin.compare(0, key.length(), key)) {
2379596a2c1Sopenharmony_ci            return iter->second;
2389596a2c1Sopenharmony_ci        }
2399596a2c1Sopenharmony_ci    }
2409596a2c1Sopenharmony_ci    return origin;
2419596a2c1Sopenharmony_ci}
2429596a2c1Sopenharmony_ci
2439596a2c1Sopenharmony_cistring GetDisplayLanguageInner(const string &language, const string &displayLocaleTag, bool sentenceCase)
2449596a2c1Sopenharmony_ci{
2459596a2c1Sopenharmony_ci    icu::UnicodeString unistr;
2469596a2c1Sopenharmony_ci    // 0 is the start position of language, 2 is the length of zh and fa
2479596a2c1Sopenharmony_ci    if (!language.compare(0, 2, "zh") || !language.compare(0, 2, "fa") || !language.compare(0, 2, "ro")) {
2489596a2c1Sopenharmony_ci        UErrorCode status = U_ZERO_ERROR;
2499596a2c1Sopenharmony_ci        icu::Locale displayLocale = icu::Locale::forLanguageTag(displayLocaleTag.c_str(), status);
2509596a2c1Sopenharmony_ci        if (U_FAILURE(status)) {
2519596a2c1Sopenharmony_ci            return "";
2529596a2c1Sopenharmony_ci        }
2539596a2c1Sopenharmony_ci        icu::LocaleDisplayNames *dspNames = icu::LocaleDisplayNames::createInstance(displayLocale,
2549596a2c1Sopenharmony_ci            UDialectHandling::ULDN_DIALECT_NAMES);
2559596a2c1Sopenharmony_ci        icu::Locale tempLocale = icu::Locale::forLanguageTag(language.c_str(), status);
2569596a2c1Sopenharmony_ci        if (U_FAILURE(status)) {
2579596a2c1Sopenharmony_ci            return "";
2589596a2c1Sopenharmony_ci        }
2599596a2c1Sopenharmony_ci        if (dspNames != nullptr) {
2609596a2c1Sopenharmony_ci            dspNames->localeDisplayName(tempLocale, unistr);
2619596a2c1Sopenharmony_ci            delete dspNames;
2629596a2c1Sopenharmony_ci        }
2639596a2c1Sopenharmony_ci    } else {
2649596a2c1Sopenharmony_ci        UErrorCode status = U_ZERO_ERROR;
2659596a2c1Sopenharmony_ci        icu::Locale displayLoc = icu::Locale::forLanguageTag(displayLocaleTag, status);
2669596a2c1Sopenharmony_ci        if (U_FAILURE(status)) {
2679596a2c1Sopenharmony_ci            return "";
2689596a2c1Sopenharmony_ci        }
2699596a2c1Sopenharmony_ci        icu::Locale locale = icu::Locale::forLanguageTag(language, status);
2709596a2c1Sopenharmony_ci        if (U_FAILURE(status)) {
2719596a2c1Sopenharmony_ci            return "";
2729596a2c1Sopenharmony_ci        }
2739596a2c1Sopenharmony_ci        locale.getDisplayName(displayLoc, unistr);
2749596a2c1Sopenharmony_ci    }
2759596a2c1Sopenharmony_ci    if (sentenceCase) {
2769596a2c1Sopenharmony_ci        UChar32 ch = ucase_toupper(unistr.char32At(0));
2779596a2c1Sopenharmony_ci        unistr.replace(0, 1, ch);
2789596a2c1Sopenharmony_ci    }
2799596a2c1Sopenharmony_ci    string out;
2809596a2c1Sopenharmony_ci    unistr.toUTF8String(out);
2819596a2c1Sopenharmony_ci    return out;
2829596a2c1Sopenharmony_ci}
2839596a2c1Sopenharmony_ci
2849596a2c1Sopenharmony_cibool LocaleConfig::listsInitialized = LocaleConfig::InitializeLists();
2859596a2c1Sopenharmony_ci
2869596a2c1Sopenharmony_cistring LocaleConfig::GetSystemLanguage()
2879596a2c1Sopenharmony_ci{
2889596a2c1Sopenharmony_ci    std::string systemLanguage = ReadSystemParameter(LANGUAGE_KEY, CONFIG_LEN);
2899596a2c1Sopenharmony_ci    if (systemLanguage.empty()) {
2909596a2c1Sopenharmony_ci        systemLanguage = ReadSystemParameter(DEFAULT_LANGUAGE_KEY, CONFIG_LEN);
2919596a2c1Sopenharmony_ci    }
2929596a2c1Sopenharmony_ci    return systemLanguage;
2939596a2c1Sopenharmony_ci}
2949596a2c1Sopenharmony_ci
2959596a2c1Sopenharmony_cistring LocaleConfig::GetSystemRegion()
2969596a2c1Sopenharmony_ci{
2979596a2c1Sopenharmony_ci    std::string systemRegion = GetCountry(LOCALE_KEY);
2989596a2c1Sopenharmony_ci    if (systemRegion.empty()) {
2999596a2c1Sopenharmony_ci        systemRegion = GetCountry(DEFAULT_LOCALE_KEY);
3009596a2c1Sopenharmony_ci    }
3019596a2c1Sopenharmony_ci    if (systemRegion.empty()) {
3029596a2c1Sopenharmony_ci        return "CN";
3039596a2c1Sopenharmony_ci    }
3049596a2c1Sopenharmony_ci    return systemRegion;
3059596a2c1Sopenharmony_ci}
3069596a2c1Sopenharmony_ci
3079596a2c1Sopenharmony_cistring LocaleConfig::GetCountry(const string& parameter)
3089596a2c1Sopenharmony_ci{
3099596a2c1Sopenharmony_ci    std::string systemRegion = ReadSystemParameter(parameter.c_str(), CONFIG_LEN);
3109596a2c1Sopenharmony_ci    if (systemRegion.empty()) {
3119596a2c1Sopenharmony_ci        HILOG_INFO_I18N("GetCountry: ReadSystemParameter %{public}s failed", parameter.c_str());
3129596a2c1Sopenharmony_ci        return systemRegion;
3139596a2c1Sopenharmony_ci    }
3149596a2c1Sopenharmony_ci    UErrorCode status = U_ZERO_ERROR;
3159596a2c1Sopenharmony_ci    icu::Locale origin = icu::Locale::forLanguageTag(systemRegion, status);
3169596a2c1Sopenharmony_ci    if (U_SUCCESS(status)) {
3179596a2c1Sopenharmony_ci        const char* country = origin.getCountry();
3189596a2c1Sopenharmony_ci        if (country != nullptr) {
3199596a2c1Sopenharmony_ci            return country;
3209596a2c1Sopenharmony_ci        }
3219596a2c1Sopenharmony_ci        HILOG_INFO_I18N("GetCountry: %{public}s get failed, country is nullptr", parameter.c_str());
3229596a2c1Sopenharmony_ci    } else {
3239596a2c1Sopenharmony_ci        HILOG_INFO_I18N("GetCountry: %{public}s get failed, U_SUCCESS is false", parameter.c_str());
3249596a2c1Sopenharmony_ci    }
3259596a2c1Sopenharmony_ci    return "";
3269596a2c1Sopenharmony_ci}
3279596a2c1Sopenharmony_ci
3289596a2c1Sopenharmony_cistring LocaleConfig::GetSystemLocale()
3299596a2c1Sopenharmony_ci{
3309596a2c1Sopenharmony_ci    std::string systemLocale = ReadSystemParameter(LOCALE_KEY, CONFIG_LEN);
3319596a2c1Sopenharmony_ci    if (systemLocale.empty()) {
3329596a2c1Sopenharmony_ci        systemLocale = ReadSystemParameter(DEFAULT_LOCALE_KEY, CONFIG_LEN);
3339596a2c1Sopenharmony_ci    }
3349596a2c1Sopenharmony_ci    return systemLocale;
3359596a2c1Sopenharmony_ci}
3369596a2c1Sopenharmony_ci
3379596a2c1Sopenharmony_cibool LocaleConfig::IsValidLanguage(const string &language)
3389596a2c1Sopenharmony_ci{
3399596a2c1Sopenharmony_ci    string::size_type size = language.size();
3409596a2c1Sopenharmony_ci    if ((size != LANGUAGE_LEN) && (size != LANGUAGE_LEN + 1)) {
3419596a2c1Sopenharmony_ci        return false;
3429596a2c1Sopenharmony_ci    }
3439596a2c1Sopenharmony_ci    for (size_t i = 0; i < size; ++i) {
3449596a2c1Sopenharmony_ci        if ((language[i] > 'z') || (language[i] < 'a')) {
3459596a2c1Sopenharmony_ci            return false;
3469596a2c1Sopenharmony_ci        }
3479596a2c1Sopenharmony_ci    }
3489596a2c1Sopenharmony_ci    return true;
3499596a2c1Sopenharmony_ci}
3509596a2c1Sopenharmony_ci
3519596a2c1Sopenharmony_cibool LocaleConfig::IsValidRegion(const string &region)
3529596a2c1Sopenharmony_ci{
3539596a2c1Sopenharmony_ci    string::size_type size = region.size();
3549596a2c1Sopenharmony_ci    if (size != LocaleInfo::REGION_LEN) {
3559596a2c1Sopenharmony_ci        return false;
3569596a2c1Sopenharmony_ci    }
3579596a2c1Sopenharmony_ci    for (size_t i = 0; i < LocaleInfo::REGION_LEN; ++i) {
3589596a2c1Sopenharmony_ci        if ((region[i] > 'Z') || (region[i] < 'A')) {
3599596a2c1Sopenharmony_ci            return false;
3609596a2c1Sopenharmony_ci        }
3619596a2c1Sopenharmony_ci    }
3629596a2c1Sopenharmony_ci    return true;
3639596a2c1Sopenharmony_ci}
3649596a2c1Sopenharmony_ci
3659596a2c1Sopenharmony_cibool LocaleConfig::IsValidTag(const string &tag)
3669596a2c1Sopenharmony_ci{
3679596a2c1Sopenharmony_ci    if (!tag.size()) {
3689596a2c1Sopenharmony_ci        return false;
3699596a2c1Sopenharmony_ci    }
3709596a2c1Sopenharmony_ci    vector<string> splits;
3719596a2c1Sopenharmony_ci    Split(tag, "-", splits);
3729596a2c1Sopenharmony_ci    if (!IsValidLanguage(splits[0])) {
3739596a2c1Sopenharmony_ci        return false;
3749596a2c1Sopenharmony_ci    }
3759596a2c1Sopenharmony_ci    return true;
3769596a2c1Sopenharmony_ci}
3779596a2c1Sopenharmony_ci
3789596a2c1Sopenharmony_civoid LocaleConfig::Split(const string &src, const string &sep, vector<string> &dest)
3799596a2c1Sopenharmony_ci{
3809596a2c1Sopenharmony_ci    string::size_type begin = 0;
3819596a2c1Sopenharmony_ci    string::size_type end = src.find(sep);
3829596a2c1Sopenharmony_ci    while (end != string::npos) {
3839596a2c1Sopenharmony_ci        dest.push_back(src.substr(begin, end - begin));
3849596a2c1Sopenharmony_ci        begin = end + sep.size();
3859596a2c1Sopenharmony_ci        end = src.find(sep, begin);
3869596a2c1Sopenharmony_ci    }
3879596a2c1Sopenharmony_ci    if (begin != src.size()) {
3889596a2c1Sopenharmony_ci        dest.push_back(src.substr(begin));
3899596a2c1Sopenharmony_ci    }
3909596a2c1Sopenharmony_ci}
3919596a2c1Sopenharmony_ci
3929596a2c1Sopenharmony_civoid LocaleConfig::Split(const string &src, const string &sep, std::unordered_set<string> &dest)
3939596a2c1Sopenharmony_ci{
3949596a2c1Sopenharmony_ci    string::size_type begin = 0;
3959596a2c1Sopenharmony_ci    string::size_type end = src.find(sep);
3969596a2c1Sopenharmony_ci    while (end != string::npos) {
3979596a2c1Sopenharmony_ci        dest.insert(src.substr(begin, end - begin));
3989596a2c1Sopenharmony_ci        begin = end + sep.size();
3999596a2c1Sopenharmony_ci        end = src.find(sep, begin);
4009596a2c1Sopenharmony_ci    }
4019596a2c1Sopenharmony_ci    if (begin != src.size()) {
4029596a2c1Sopenharmony_ci        dest.insert(src.substr(begin));
4039596a2c1Sopenharmony_ci    }
4049596a2c1Sopenharmony_ci}
4059596a2c1Sopenharmony_ci
4069596a2c1Sopenharmony_ci// language in white languages should have script.
4079596a2c1Sopenharmony_civoid LocaleConfig::GetSystemLanguages(vector<string> &ret)
4089596a2c1Sopenharmony_ci{
4099596a2c1Sopenharmony_ci    std::copy(whiteLanguages.begin(), whiteLanguages.end(), std::back_inserter(ret));
4109596a2c1Sopenharmony_ci}
4119596a2c1Sopenharmony_ci
4129596a2c1Sopenharmony_ciconst unordered_set<string>& LocaleConfig::GetSupportedLocales()
4139596a2c1Sopenharmony_ci{
4149596a2c1Sopenharmony_ci    return supportedLocales;
4159596a2c1Sopenharmony_ci}
4169596a2c1Sopenharmony_ci
4179596a2c1Sopenharmony_ciconst unordered_set<string>& LocaleConfig::GetSupportedRegions()
4189596a2c1Sopenharmony_ci{
4199596a2c1Sopenharmony_ci    return supportedRegions;
4209596a2c1Sopenharmony_ci}
4219596a2c1Sopenharmony_ci
4229596a2c1Sopenharmony_civoid LocaleConfig::GetSystemCountries(vector<string> &ret)
4239596a2c1Sopenharmony_ci{
4249596a2c1Sopenharmony_ci    std::copy(supportedRegions.begin(), supportedRegions.end(), std::back_inserter(ret));
4259596a2c1Sopenharmony_ci}
4269596a2c1Sopenharmony_ci
4279596a2c1Sopenharmony_cibool LocaleConfig::IsSuggested(const string &language)
4289596a2c1Sopenharmony_ci{
4299596a2c1Sopenharmony_ci    unordered_set<string> relatedLocales;
4309596a2c1Sopenharmony_ci    vector<string> simCountries;
4319596a2c1Sopenharmony_ci    GetCountriesFromSim(simCountries);
4329596a2c1Sopenharmony_ci    GetRelatedLocales(relatedLocales, simCountries);
4339596a2c1Sopenharmony_ci    for (auto iter = relatedLocales.begin(); iter != relatedLocales.end();) {
4349596a2c1Sopenharmony_ci        if (extendWhiteLanguageList.find(*iter) == extendWhiteLanguageList.end()) {
4359596a2c1Sopenharmony_ci            iter = relatedLocales.erase(iter);
4369596a2c1Sopenharmony_ci        } else {
4379596a2c1Sopenharmony_ci            ++iter;
4389596a2c1Sopenharmony_ci        }
4399596a2c1Sopenharmony_ci    }
4409596a2c1Sopenharmony_ci    string mainLanguage = GetMainLanguage(language);
4419596a2c1Sopenharmony_ci    return relatedLocales.find(mainLanguage) != relatedLocales.end();
4429596a2c1Sopenharmony_ci}
4439596a2c1Sopenharmony_ci
4449596a2c1Sopenharmony_cibool LocaleConfig::IsSuggested(const std::string &language, const std::string &region)
4459596a2c1Sopenharmony_ci{
4469596a2c1Sopenharmony_ci    unordered_set<string> relatedLocales;
4479596a2c1Sopenharmony_ci    vector<string> countries { region };
4489596a2c1Sopenharmony_ci    GetRelatedLocales(relatedLocales, countries);
4499596a2c1Sopenharmony_ci    for (auto iter = relatedLocales.begin(); iter != relatedLocales.end();) {
4509596a2c1Sopenharmony_ci        if (extendWhiteLanguageList.find(*iter) == extendWhiteLanguageList.end()) {
4519596a2c1Sopenharmony_ci            iter = relatedLocales.erase(iter);
4529596a2c1Sopenharmony_ci        } else {
4539596a2c1Sopenharmony_ci            ++iter;
4549596a2c1Sopenharmony_ci        }
4559596a2c1Sopenharmony_ci    }
4569596a2c1Sopenharmony_ci    string mainLanguage = GetMainLanguage(language);
4579596a2c1Sopenharmony_ci    return relatedLocales.find(mainLanguage) != relatedLocales.end();
4589596a2c1Sopenharmony_ci}
4599596a2c1Sopenharmony_ci
4609596a2c1Sopenharmony_civoid LocaleConfig::ExtendWhiteLanguages()
4619596a2c1Sopenharmony_ci{
4629596a2c1Sopenharmony_ci    UErrorCode status = U_ZERO_ERROR;
4639596a2c1Sopenharmony_ci    for (auto iter = whiteLanguages.begin(); iter != whiteLanguages.end(); ++iter) {
4649596a2c1Sopenharmony_ci        extendWhiteLanguageList.insert(*iter);
4659596a2c1Sopenharmony_ci        icu::Locale locale = icu::Locale::forLanguageTag((*iter).c_str(), status);
4669596a2c1Sopenharmony_ci        locale.addLikelySubtags(status);
4679596a2c1Sopenharmony_ci        if (U_FAILURE(status)) {
4689596a2c1Sopenharmony_ci            HILOG_INFO_I18N("create Locale object for %{public}s failed.", (*iter).c_str());
4699596a2c1Sopenharmony_ci            continue;
4709596a2c1Sopenharmony_ci        }
4719596a2c1Sopenharmony_ci        const char* baseName = locale.getBaseName();
4729596a2c1Sopenharmony_ci        if (baseName != nullptr) {
4739596a2c1Sopenharmony_ci            std::string baseNameStr(baseName);
4749596a2c1Sopenharmony_ci            std::replace(baseNameStr.begin(), baseNameStr.end(), '_', '-');
4759596a2c1Sopenharmony_ci            extendWhiteLanguageList.insert(baseNameStr);
4769596a2c1Sopenharmony_ci        }
4779596a2c1Sopenharmony_ci    }
4789596a2c1Sopenharmony_ci}
4799596a2c1Sopenharmony_ci
4809596a2c1Sopenharmony_civoid LocaleConfig::GetRelatedLocales(unordered_set<string> &relatedLocales, vector<string> countries)
4819596a2c1Sopenharmony_ci{
4829596a2c1Sopenharmony_ci    // remove unsupported countries
4839596a2c1Sopenharmony_ci    const unordered_set<string> &regions = GetSupportedRegions();
4849596a2c1Sopenharmony_ci    for (auto iter = countries.begin(); iter != countries.end();) {
4859596a2c1Sopenharmony_ci        if (regions.find(*iter) == regions.end()) {
4869596a2c1Sopenharmony_ci            iter = countries.erase(iter);
4879596a2c1Sopenharmony_ci        } else {
4889596a2c1Sopenharmony_ci            ++iter;
4899596a2c1Sopenharmony_ci        }
4909596a2c1Sopenharmony_ci    }
4919596a2c1Sopenharmony_ci    const unordered_set<string> &locales = GetSupportedLocales();
4929596a2c1Sopenharmony_ci    for (string locale : locales) {
4939596a2c1Sopenharmony_ci        bool find = false;
4949596a2c1Sopenharmony_ci        for (string country : countries) {
4959596a2c1Sopenharmony_ci            if (locale.find(country) != string::npos) {
4969596a2c1Sopenharmony_ci                find = true;
4979596a2c1Sopenharmony_ci                break;
4989596a2c1Sopenharmony_ci            }
4999596a2c1Sopenharmony_ci        }
5009596a2c1Sopenharmony_ci        if (!find) {
5019596a2c1Sopenharmony_ci            continue;
5029596a2c1Sopenharmony_ci        }
5039596a2c1Sopenharmony_ci        string mainLanguage = GetMainLanguage(locale);
5049596a2c1Sopenharmony_ci        if (mainLanguage != "") {
5059596a2c1Sopenharmony_ci            relatedLocales.insert(mainLanguage);
5069596a2c1Sopenharmony_ci        }
5079596a2c1Sopenharmony_ci    }
5089596a2c1Sopenharmony_ci}
5099596a2c1Sopenharmony_ci
5109596a2c1Sopenharmony_civoid LocaleConfig::GetCountriesFromSim(vector<string> &simCountries)
5119596a2c1Sopenharmony_ci{
5129596a2c1Sopenharmony_ci    simCountries.push_back(GetSystemRegion());
5139596a2c1Sopenharmony_ci    char value[CONFIG_LEN];
5149596a2c1Sopenharmony_ci    int code = GetParameter(SIM_COUNTRY_CODE_KEY, "", value, CONFIG_LEN);
5159596a2c1Sopenharmony_ci    if (code > 0) {
5169596a2c1Sopenharmony_ci        simCountries.push_back(value);
5179596a2c1Sopenharmony_ci    }
5189596a2c1Sopenharmony_ci}
5199596a2c1Sopenharmony_ci
5209596a2c1Sopenharmony_civoid LocaleConfig::GetListFromFile(const char *path, const char *resourceName, unordered_set<string> &ret)
5219596a2c1Sopenharmony_ci{
5229596a2c1Sopenharmony_ci    xmlKeepBlanksDefault(0);
5239596a2c1Sopenharmony_ci    if (!path) {
5249596a2c1Sopenharmony_ci        return;
5259596a2c1Sopenharmony_ci    }
5269596a2c1Sopenharmony_ci    xmlDocPtr doc = xmlParseFile(path);
5279596a2c1Sopenharmony_ci    if (!doc) {
5289596a2c1Sopenharmony_ci        return;
5299596a2c1Sopenharmony_ci    }
5309596a2c1Sopenharmony_ci    xmlNodePtr cur = xmlDocGetRootElement(doc);
5319596a2c1Sopenharmony_ci    if (!cur || xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>(resourceName))) {
5329596a2c1Sopenharmony_ci        xmlFreeDoc(doc);
5339596a2c1Sopenharmony_ci        return;
5349596a2c1Sopenharmony_ci    }
5359596a2c1Sopenharmony_ci    cur = cur->xmlChildrenNode;
5369596a2c1Sopenharmony_ci    xmlChar *content = nullptr;
5379596a2c1Sopenharmony_ci    while (cur != nullptr) {
5389596a2c1Sopenharmony_ci        content = xmlNodeGetContent(cur);
5399596a2c1Sopenharmony_ci        if (content != nullptr) {
5409596a2c1Sopenharmony_ci            ret.insert(reinterpret_cast<const char*>(content));
5419596a2c1Sopenharmony_ci            xmlFree(content);
5429596a2c1Sopenharmony_ci            cur = cur->next;
5439596a2c1Sopenharmony_ci        } else {
5449596a2c1Sopenharmony_ci            break;
5459596a2c1Sopenharmony_ci        }
5469596a2c1Sopenharmony_ci    }
5479596a2c1Sopenharmony_ci    xmlFreeDoc(doc);
5489596a2c1Sopenharmony_ci}
5499596a2c1Sopenharmony_ci
5509596a2c1Sopenharmony_civoid LocaleConfig::ProcessForbiddenRegions(const unordered_set<string> &forbiddenRegions)
5519596a2c1Sopenharmony_ci{
5529596a2c1Sopenharmony_ci    for (auto it = forbiddenRegions.begin(); it != forbiddenRegions.end(); ++it) {
5539596a2c1Sopenharmony_ci        size_t pos = it->rfind("-");
5549596a2c1Sopenharmony_ci        std::string language = it->substr(0, pos);
5559596a2c1Sopenharmony_ci        std::string region = it->substr(pos + 1);
5569596a2c1Sopenharmony_ci        if (language.compare("*") == 0) {
5579596a2c1Sopenharmony_ci            blockedRegions.insert(region);
5589596a2c1Sopenharmony_ci        } else {
5599596a2c1Sopenharmony_ci            if (blockedLanguageRegions.find(language) == blockedLanguageRegions.end()) {
5609596a2c1Sopenharmony_ci                blockedLanguageRegions[language] = { region };
5619596a2c1Sopenharmony_ci            } else {
5629596a2c1Sopenharmony_ci                blockedLanguageRegions[language].insert(region);
5639596a2c1Sopenharmony_ci            }
5649596a2c1Sopenharmony_ci        }
5659596a2c1Sopenharmony_ci    }
5669596a2c1Sopenharmony_ci}
5679596a2c1Sopenharmony_ci
5689596a2c1Sopenharmony_civoid LocaleConfig::Expunge(unordered_set<string> &src, const unordered_set<string> &another)
5699596a2c1Sopenharmony_ci{
5709596a2c1Sopenharmony_ci    for (auto iter = src.begin(); iter != src.end();) {
5719596a2c1Sopenharmony_ci        if (another.find(*iter) != another.end()) {
5729596a2c1Sopenharmony_ci            iter = src.erase(iter);
5739596a2c1Sopenharmony_ci        } else {
5749596a2c1Sopenharmony_ci            ++iter;
5759596a2c1Sopenharmony_ci        }
5769596a2c1Sopenharmony_ci    }
5779596a2c1Sopenharmony_ci}
5789596a2c1Sopenharmony_ci
5799596a2c1Sopenharmony_cibool LocaleConfig::InitializeLists()
5809596a2c1Sopenharmony_ci{
5819596a2c1Sopenharmony_ci    SetHwIcuDirectory();
5829596a2c1Sopenharmony_ci    unordered_set<string> forbiddenRegions;
5839596a2c1Sopenharmony_ci    LoadRegionsLanguages(forbiddenRegions);
5849596a2c1Sopenharmony_ci    ProcessForbiddenRegions(forbiddenRegions);
5859596a2c1Sopenharmony_ci    Expunge(supportedRegions, blockedRegions);
5869596a2c1Sopenharmony_ci    Expunge(whiteLanguages, blockedLanguages);
5879596a2c1Sopenharmony_ci    GetListFromFile(SUPPORTED_LOCALES_PATH, SUPPORTED_LOCALES_NAME, supportedLocales);
5889596a2c1Sopenharmony_ci    GetListFromFile(SUPPORT_LOCALES_PATH, SUPPORT_LOCALES_NAME, supportLocales);
5899596a2c1Sopenharmony_ci    GetListFromFile(OVERRIDE_SUPPORTED_REGIONS_PATH, OVERRIDE_SUPPORTED_REGIONS_NAME, overrideSupportedRegions);
5909596a2c1Sopenharmony_ci    GetListFromFile(DIALECT_LANGS_PATH, DIALECT_LANGS_NAME, dialectLang);
5919596a2c1Sopenharmony_ci    ExtendWhiteLanguages();
5929596a2c1Sopenharmony_ci    return true;
5939596a2c1Sopenharmony_ci}
5949596a2c1Sopenharmony_ci
5959596a2c1Sopenharmony_civoid LocaleConfig::LoadRegionsLanguages(unordered_set<std::string>& forbiddenRegions)
5969596a2c1Sopenharmony_ci{
5979596a2c1Sopenharmony_ci    char buf[MAX_PATH_LEN] = {0};
5989596a2c1Sopenharmony_ci    char* path = GetOneCfgFile(REGIONS_LANGUAGES_PATH, buf, MAX_PATH_LEN);
5999596a2c1Sopenharmony_ci    xmlKeepBlanksDefault(0);
6009596a2c1Sopenharmony_ci    if (!path) {
6019596a2c1Sopenharmony_ci        return;
6029596a2c1Sopenharmony_ci    }
6039596a2c1Sopenharmony_ci    xmlDocPtr doc = xmlParseFile(path);
6049596a2c1Sopenharmony_ci    if (!doc) {
6059596a2c1Sopenharmony_ci        return;
6069596a2c1Sopenharmony_ci    }
6079596a2c1Sopenharmony_ci    xmlNodePtr cur = xmlDocGetRootElement(doc);
6089596a2c1Sopenharmony_ci    if (!cur || xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>(REGIONS_LANGUAGES_NAME))) {
6099596a2c1Sopenharmony_ci        xmlFreeDoc(doc);
6109596a2c1Sopenharmony_ci        return;
6119596a2c1Sopenharmony_ci    }
6129596a2c1Sopenharmony_ci    cur = cur->xmlChildrenNode;
6139596a2c1Sopenharmony_ci    xmlChar *content = nullptr;
6149596a2c1Sopenharmony_ci    while (cur != nullptr) {
6159596a2c1Sopenharmony_ci        content = xmlNodeGetContent(cur);
6169596a2c1Sopenharmony_ci        if (content != nullptr && !xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>(SUPPORTED_REGIONS_NAME))) {
6179596a2c1Sopenharmony_ci            Split(reinterpret_cast<const char*>(content), ",", supportedRegions);
6189596a2c1Sopenharmony_ci        } else if (content != nullptr && !xmlStrcmp(cur->name,
6199596a2c1Sopenharmony_ci            reinterpret_cast<const xmlChar *>(WHITE_LANGUAGES_NAME))) {
6209596a2c1Sopenharmony_ci            Split(reinterpret_cast<const char*>(content), ",", whiteLanguages);
6219596a2c1Sopenharmony_ci        } else if (content != nullptr && !xmlStrcmp(cur->name,
6229596a2c1Sopenharmony_ci            reinterpret_cast<const xmlChar *>(FORBIDDEN_REGIONS_NAME))) {
6239596a2c1Sopenharmony_ci            Split(reinterpret_cast<const char*>(content), ",", forbiddenRegions);
6249596a2c1Sopenharmony_ci        } else if (content != nullptr && !xmlStrcmp(cur->name,
6259596a2c1Sopenharmony_ci            reinterpret_cast<const xmlChar *>(FORBIDDEN_LANGUAGES_NAME))) {
6269596a2c1Sopenharmony_ci            Split(reinterpret_cast<const char*>(content), ",", blockedLanguages);
6279596a2c1Sopenharmony_ci        }
6289596a2c1Sopenharmony_ci        if (content != nullptr) {
6299596a2c1Sopenharmony_ci            xmlFree(content);
6309596a2c1Sopenharmony_ci        }
6319596a2c1Sopenharmony_ci        cur = cur->next;
6329596a2c1Sopenharmony_ci    }
6339596a2c1Sopenharmony_ci    xmlFreeDoc(doc);
6349596a2c1Sopenharmony_ci}
6359596a2c1Sopenharmony_ci
6369596a2c1Sopenharmony_cistring LocaleConfig::GetMainLanguage(const string &language)
6379596a2c1Sopenharmony_ci{
6389596a2c1Sopenharmony_ci    UErrorCode status = U_ZERO_ERROR;
6399596a2c1Sopenharmony_ci    icu::Locale origin = icu::Locale::forLanguageTag(language, status);
6409596a2c1Sopenharmony_ci    if (U_FAILURE(status)) {
6419596a2c1Sopenharmony_ci        return "";
6429596a2c1Sopenharmony_ci    }
6439596a2c1Sopenharmony_ci    origin.addLikelySubtags(status);
6449596a2c1Sopenharmony_ci    if (U_FAILURE(status)) {
6459596a2c1Sopenharmony_ci        return "";
6469596a2c1Sopenharmony_ci    }
6479596a2c1Sopenharmony_ci    icu::LocaleBuilder builder = icu::LocaleBuilder().setLanguage(origin.getLanguage()).
6489596a2c1Sopenharmony_ci        setScript(origin.getScript()).setRegion(origin.getCountry());
6499596a2c1Sopenharmony_ci    icu::Locale temp = builder.setExtension('u', "").build(status);
6509596a2c1Sopenharmony_ci    if (U_FAILURE(status)) {
6519596a2c1Sopenharmony_ci        return "";
6529596a2c1Sopenharmony_ci    }
6539596a2c1Sopenharmony_ci    string fullLanguage = temp.toLanguageTag<string>(status);
6549596a2c1Sopenharmony_ci    if (U_FAILURE(status)) {
6559596a2c1Sopenharmony_ci        return "";
6569596a2c1Sopenharmony_ci    }
6579596a2c1Sopenharmony_ci    if (dialectMap.find(fullLanguage) != dialectMap.end()) {
6589596a2c1Sopenharmony_ci        return dialectMap[fullLanguage];
6599596a2c1Sopenharmony_ci    }
6609596a2c1Sopenharmony_ci    builder.setRegion("");
6619596a2c1Sopenharmony_ci    temp = builder.build(status);
6629596a2c1Sopenharmony_ci    if (U_FAILURE(status)) {
6639596a2c1Sopenharmony_ci        return "";
6649596a2c1Sopenharmony_ci    }
6659596a2c1Sopenharmony_ci    fullLanguage = temp.toLanguageTag<string>(status);
6669596a2c1Sopenharmony_ci    if (U_FAILURE(status)) {
6679596a2c1Sopenharmony_ci        return "";
6689596a2c1Sopenharmony_ci    }
6699596a2c1Sopenharmony_ci    return fullLanguage;
6709596a2c1Sopenharmony_ci}
6719596a2c1Sopenharmony_ci
6729596a2c1Sopenharmony_cistring LocaleConfig::GetDisplayLanguage(const string &language, const string &displayLocale, bool sentenceCase)
6739596a2c1Sopenharmony_ci{
6749596a2c1Sopenharmony_ci    std::string result;
6759596a2c1Sopenharmony_ci    string adjust = Adjust(language);
6769596a2c1Sopenharmony_ci    if (adjust == language) {
6779596a2c1Sopenharmony_ci        UErrorCode status = U_ZERO_ERROR;
6789596a2c1Sopenharmony_ci        icu::Locale displayLoc = icu::Locale::forLanguageTag(displayLocale, status);
6799596a2c1Sopenharmony_ci        if (U_FAILURE(status)) {
6809596a2c1Sopenharmony_ci            return PseudoLocalizationProcessor("");
6819596a2c1Sopenharmony_ci        }
6829596a2c1Sopenharmony_ci        icu::Locale locale = icu::Locale::forLanguageTag(language, status);
6839596a2c1Sopenharmony_ci        if (U_FAILURE(status)) {
6849596a2c1Sopenharmony_ci            return PseudoLocalizationProcessor("");
6859596a2c1Sopenharmony_ci        }
6869596a2c1Sopenharmony_ci        icu::UnicodeString unistr;
6879596a2c1Sopenharmony_ci        std::string lang(locale.getLanguage());
6889596a2c1Sopenharmony_ci        if (dialectLang.find(lang) != dialectLang.end()) {
6899596a2c1Sopenharmony_ci            result = GetDisplayLanguageWithDialect(language, displayLocale);
6909596a2c1Sopenharmony_ci        }
6919596a2c1Sopenharmony_ci    }
6929596a2c1Sopenharmony_ci    if (result.empty()) {
6939596a2c1Sopenharmony_ci        result = GetDisplayLanguageInner(adjust, displayLocale, sentenceCase);
6949596a2c1Sopenharmony_ci    }
6959596a2c1Sopenharmony_ci    if (sentenceCase && !result.empty()) {
6969596a2c1Sopenharmony_ci        char ch = static_cast<char>(toupper(result[0]));
6979596a2c1Sopenharmony_ci        return PseudoLocalizationProcessor(result.replace(0, 1, 1, ch));
6989596a2c1Sopenharmony_ci    }
6999596a2c1Sopenharmony_ci    return PseudoLocalizationProcessor(result);
7009596a2c1Sopenharmony_ci}
7019596a2c1Sopenharmony_ci
7029596a2c1Sopenharmony_cistd::string LocaleConfig::ComputeLocale(const std::string &displayLocale)
7039596a2c1Sopenharmony_ci{
7049596a2c1Sopenharmony_ci    if (supportedDialectLocales.size() == 0) {
7059596a2c1Sopenharmony_ci        xmlKeepBlanksDefault(0);
7069596a2c1Sopenharmony_ci        xmlDocPtr doc = xmlParseFile(SUPPORT_LOCALES_PATH);
7079596a2c1Sopenharmony_ci        if (!doc) {
7089596a2c1Sopenharmony_ci            return "";
7099596a2c1Sopenharmony_ci        }
7109596a2c1Sopenharmony_ci        xmlNodePtr cur = xmlDocGetRootElement(doc);
7119596a2c1Sopenharmony_ci        if (!cur || xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>(supportLocalesTag))) {
7129596a2c1Sopenharmony_ci            xmlFreeDoc(doc);
7139596a2c1Sopenharmony_ci            HILOG_INFO_I18N("can not parse language supported locale file");
7149596a2c1Sopenharmony_ci            return "";
7159596a2c1Sopenharmony_ci        }
7169596a2c1Sopenharmony_ci        cur = cur->xmlChildrenNode;
7179596a2c1Sopenharmony_ci        while (cur != nullptr) {
7189596a2c1Sopenharmony_ci            xmlChar *content = xmlNodeGetContent(cur);
7199596a2c1Sopenharmony_ci            if (content == nullptr) {
7209596a2c1Sopenharmony_ci                HILOG_INFO_I18N("get xml node content failed");
7219596a2c1Sopenharmony_ci                break;
7229596a2c1Sopenharmony_ci            }
7239596a2c1Sopenharmony_ci            std::map<std::string, std::string> localeInfoConfigs = {};
7249596a2c1Sopenharmony_ci            LocaleInfo localeinfo(reinterpret_cast<const char*>(content), localeInfoConfigs);
7259596a2c1Sopenharmony_ci            std::string maximizeLocale = localeinfo.Maximize();
7269596a2c1Sopenharmony_ci            const char* key = maximizeLocale.c_str();
7279596a2c1Sopenharmony_ci            const char* value = reinterpret_cast<const char*>(content);
7289596a2c1Sopenharmony_ci            SetSupportedDialectLocales(key, value);
7299596a2c1Sopenharmony_ci            xmlFree(content);
7309596a2c1Sopenharmony_ci            cur = cur->next;
7319596a2c1Sopenharmony_ci        }
7329596a2c1Sopenharmony_ci        xmlFreeDoc(doc);
7339596a2c1Sopenharmony_ci    }
7349596a2c1Sopenharmony_ci    std::map<std::string, std::string> configs = {};
7359596a2c1Sopenharmony_ci    LocaleInfo localeinfo(displayLocale, configs);
7369596a2c1Sopenharmony_ci    std::string maximizeLocale = localeinfo.Maximize();
7379596a2c1Sopenharmony_ci    if (supportedDialectLocales.find(maximizeLocale) != supportedDialectLocales.end()) {
7389596a2c1Sopenharmony_ci        return supportedDialectLocales.at(maximizeLocale);
7399596a2c1Sopenharmony_ci    }
7409596a2c1Sopenharmony_ci    return "";
7419596a2c1Sopenharmony_ci}
7429596a2c1Sopenharmony_ci
7439596a2c1Sopenharmony_civoid LocaleConfig::SetSupportedDialectLocales(const char* key, const char* value)
7449596a2c1Sopenharmony_ci{
7459596a2c1Sopenharmony_ci    std::lock_guard<std::mutex> dialectLocaleLock(dialectLocaleMutex);
7469596a2c1Sopenharmony_ci    supportedDialectLocales.insert(
7479596a2c1Sopenharmony_ci        std::make_pair<std::string, std::string>(key, value));
7489596a2c1Sopenharmony_ci}
7499596a2c1Sopenharmony_ci
7509596a2c1Sopenharmony_civoid LocaleConfig::ReadLangData(const char *langDataPath)
7519596a2c1Sopenharmony_ci{
7529596a2c1Sopenharmony_ci    xmlKeepBlanksDefault(0);
7539596a2c1Sopenharmony_ci    if (langDataPath == nullptr) {
7549596a2c1Sopenharmony_ci        return;
7559596a2c1Sopenharmony_ci    }
7569596a2c1Sopenharmony_ci    xmlDocPtr doc = xmlParseFile(langDataPath);
7579596a2c1Sopenharmony_ci    if (!doc) {
7589596a2c1Sopenharmony_ci        HILOG_INFO_I18N("can not open language data file");
7599596a2c1Sopenharmony_ci        return;
7609596a2c1Sopenharmony_ci    }
7619596a2c1Sopenharmony_ci    xmlNodePtr cur = xmlDocGetRootElement(doc);
7629596a2c1Sopenharmony_ci    if (!cur || xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>(rootTag))) {
7639596a2c1Sopenharmony_ci        xmlFreeDoc(doc);
7649596a2c1Sopenharmony_ci        HILOG_INFO_I18N("parse language data file failed");
7659596a2c1Sopenharmony_ci        return;
7669596a2c1Sopenharmony_ci    }
7679596a2c1Sopenharmony_ci    cur = cur->xmlChildrenNode;
7689596a2c1Sopenharmony_ci    while (cur != nullptr && !xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>(secondRootTag))) {
7699596a2c1Sopenharmony_ci        xmlChar *langContents[ELEMENT_NUM] = { 0 }; // 2 represent langid, displayname;
7709596a2c1Sopenharmony_ci        xmlNodePtr langValue = cur->xmlChildrenNode;
7719596a2c1Sopenharmony_ci        bool xmlNodeNull = false;
7729596a2c1Sopenharmony_ci        for (size_t i = 0; i < ELEMENT_NUM && langValue != nullptr; i++) {
7739596a2c1Sopenharmony_ci            langContents[i] = xmlNodeGetContent(langValue);
7749596a2c1Sopenharmony_ci            langValue = langValue->next;
7759596a2c1Sopenharmony_ci            if (langContents[i] == nullptr) {
7769596a2c1Sopenharmony_ci                xmlNodeNull = true;
7779596a2c1Sopenharmony_ci            }
7789596a2c1Sopenharmony_ci        }
7799596a2c1Sopenharmony_ci        if (!xmlNodeNull) {
7809596a2c1Sopenharmony_ci            // 0 represents langid index, 1 represents displayname index
7819596a2c1Sopenharmony_ci            const char* key = reinterpret_cast<const char *>(langContents[0]);
7829596a2c1Sopenharmony_ci            const char* value = reinterpret_cast<const char *>(langContents[1]);
7839596a2c1Sopenharmony_ci            SetLocale2DisplayName(key, value);
7849596a2c1Sopenharmony_ci        }
7859596a2c1Sopenharmony_ci        for (size_t i = 0; i < ELEMENT_NUM; i++) {
7869596a2c1Sopenharmony_ci            if (langContents[i] != nullptr) {
7879596a2c1Sopenharmony_ci                xmlFree(langContents[i]);
7889596a2c1Sopenharmony_ci            }
7899596a2c1Sopenharmony_ci        }
7909596a2c1Sopenharmony_ci        cur = cur->next;
7919596a2c1Sopenharmony_ci    }
7929596a2c1Sopenharmony_ci    xmlFreeDoc(doc);
7939596a2c1Sopenharmony_ci}
7949596a2c1Sopenharmony_ci
7959596a2c1Sopenharmony_civoid LocaleConfig::SetRegion2DisplayName(const char* key, const char* value)
7969596a2c1Sopenharmony_ci{
7979596a2c1Sopenharmony_ci    std::lock_guard<std::mutex> regionDisplayLock(region2DisplayNameMutex);
7989596a2c1Sopenharmony_ci    region2DisplayName.insert(
7999596a2c1Sopenharmony_ci        std::make_pair<std::string, std::string>(key, value));
8009596a2c1Sopenharmony_ci}
8019596a2c1Sopenharmony_ci
8029596a2c1Sopenharmony_civoid LocaleConfig::SetLocale2DisplayName(const char* key, const char* value)
8039596a2c1Sopenharmony_ci{
8049596a2c1Sopenharmony_ci    std::lock_guard<std::mutex> localeDisplayLock(locale2DisplayNameMutex);
8059596a2c1Sopenharmony_ci    locale2DisplayName.insert(
8069596a2c1Sopenharmony_ci        std::make_pair<std::string, std::string>(key, value));
8079596a2c1Sopenharmony_ci}
8089596a2c1Sopenharmony_ci
8099596a2c1Sopenharmony_civoid LocaleConfig::ReadRegionData(const char *regionDataPath)
8109596a2c1Sopenharmony_ci{
8119596a2c1Sopenharmony_ci    xmlKeepBlanksDefault(0);
8129596a2c1Sopenharmony_ci    if (regionDataPath == nullptr) {
8139596a2c1Sopenharmony_ci        return;
8149596a2c1Sopenharmony_ci    }
8159596a2c1Sopenharmony_ci    xmlDocPtr doc = xmlParseFile(regionDataPath);
8169596a2c1Sopenharmony_ci    if (!doc) {
8179596a2c1Sopenharmony_ci        HILOG_INFO_I18N("can not open region data file");
8189596a2c1Sopenharmony_ci        return;
8199596a2c1Sopenharmony_ci    }
8209596a2c1Sopenharmony_ci    xmlNodePtr cur = xmlDocGetRootElement(doc);
8219596a2c1Sopenharmony_ci    if (cur) {
8229596a2c1Sopenharmony_ci        HILOG_INFO_I18N("cur pointer is true");
8239596a2c1Sopenharmony_ci    }
8249596a2c1Sopenharmony_ci    if (!cur || xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>(rootRegion))) {
8259596a2c1Sopenharmony_ci        xmlFreeDoc(doc);
8269596a2c1Sopenharmony_ci        HILOG_INFO_I18N("parse region data file failed");
8279596a2c1Sopenharmony_ci        return;
8289596a2c1Sopenharmony_ci    }
8299596a2c1Sopenharmony_ci    cur = cur->xmlChildrenNode;
8309596a2c1Sopenharmony_ci    while (cur != nullptr && !xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>(secondRootRegion))) {
8319596a2c1Sopenharmony_ci        xmlChar *regionContents[ELEMENT_NUM] = { 0 };
8329596a2c1Sopenharmony_ci        xmlNodePtr regionValue = cur->xmlChildrenNode;
8339596a2c1Sopenharmony_ci        bool xmlNodeNull = false;
8349596a2c1Sopenharmony_ci        for (size_t i = 0; i < ELEMENT_NUM && regionValue != nullptr; i++) {
8359596a2c1Sopenharmony_ci            regionContents[i] = xmlNodeGetContent(regionValue);
8369596a2c1Sopenharmony_ci            regionValue = regionValue->next;
8379596a2c1Sopenharmony_ci            if (regionContents[i] == nullptr) {
8389596a2c1Sopenharmony_ci                xmlNodeNull = true;
8399596a2c1Sopenharmony_ci            }
8409596a2c1Sopenharmony_ci        }
8419596a2c1Sopenharmony_ci        if (!xmlNodeNull) {
8429596a2c1Sopenharmony_ci            // 0 represents langid index, 1 represents displayname index
8439596a2c1Sopenharmony_ci            const char* regionKey = reinterpret_cast<const char *>(regionContents[0]);
8449596a2c1Sopenharmony_ci            const char* regionVal = reinterpret_cast<const char *>(regionContents[1]);
8459596a2c1Sopenharmony_ci            SetRegion2DisplayName(regionKey, regionVal);
8469596a2c1Sopenharmony_ci        }
8479596a2c1Sopenharmony_ci        for (size_t i = 0; i < ELEMENT_NUM; i++) {
8489596a2c1Sopenharmony_ci            if (regionContents[i] != nullptr) {
8499596a2c1Sopenharmony_ci                xmlFree(regionContents[i]);
8509596a2c1Sopenharmony_ci            }
8519596a2c1Sopenharmony_ci        }
8529596a2c1Sopenharmony_ci        cur = cur->next;
8539596a2c1Sopenharmony_ci    }
8549596a2c1Sopenharmony_ci    xmlFreeDoc(doc);
8559596a2c1Sopenharmony_ci}
8569596a2c1Sopenharmony_ci
8579596a2c1Sopenharmony_cistring LocaleConfig::GetDisplayLanguageWithDialect(const std::string &localeStr, const std::string &displayLocale)
8589596a2c1Sopenharmony_ci{
8599596a2c1Sopenharmony_ci    std::string finalLocale = ComputeLocale(displayLocale);
8609596a2c1Sopenharmony_ci    if (finalLocale.empty()) {
8619596a2c1Sopenharmony_ci        return "";
8629596a2c1Sopenharmony_ci    }
8639596a2c1Sopenharmony_ci    if (finalLocale.compare(currentDialectLocale) != 0) {
8649596a2c1Sopenharmony_ci        std::string xmlPath = LANG_PATH + finalLocale + ".xml";
8659596a2c1Sopenharmony_ci        locale2DisplayName.clear();
8669596a2c1Sopenharmony_ci        ReadLangData(xmlPath.c_str());
8679596a2c1Sopenharmony_ci        currentDialectLocale = finalLocale;
8689596a2c1Sopenharmony_ci    }
8699596a2c1Sopenharmony_ci    if (locale2DisplayName.find(localeStr) != locale2DisplayName.end()) {
8709596a2c1Sopenharmony_ci        return locale2DisplayName.at(localeStr);
8719596a2c1Sopenharmony_ci    }
8729596a2c1Sopenharmony_ci    std::map<std::string, std::string> configs = {};
8739596a2c1Sopenharmony_ci    LocaleInfo locale(localeStr, configs);
8749596a2c1Sopenharmony_ci    std::string language = locale.GetLanguage();
8759596a2c1Sopenharmony_ci    std::string scripts = locale.GetScript();
8769596a2c1Sopenharmony_ci    std::string region = locale.GetRegion();
8779596a2c1Sopenharmony_ci    if (scripts.length() != 0) {
8789596a2c1Sopenharmony_ci        std::string languageAndScripts = language + "-" + scripts;
8799596a2c1Sopenharmony_ci        if (locale2DisplayName.find(languageAndScripts) != locale2DisplayName.end()) {
8809596a2c1Sopenharmony_ci            return locale2DisplayName.at(languageAndScripts);
8819596a2c1Sopenharmony_ci        }
8829596a2c1Sopenharmony_ci    }
8839596a2c1Sopenharmony_ci    if (region.length() != 0) {
8849596a2c1Sopenharmony_ci        std::string languageAndRegion = language + "-" + region;
8859596a2c1Sopenharmony_ci        if (locale2DisplayName.find(languageAndRegion) != locale2DisplayName.end()) {
8869596a2c1Sopenharmony_ci            return locale2DisplayName.at(languageAndRegion);
8879596a2c1Sopenharmony_ci        }
8889596a2c1Sopenharmony_ci    }
8899596a2c1Sopenharmony_ci    if (locale2DisplayName.find(language) != locale2DisplayName.end()) {
8909596a2c1Sopenharmony_ci        return locale2DisplayName.at(language);
8919596a2c1Sopenharmony_ci    }
8929596a2c1Sopenharmony_ci    return "";
8939596a2c1Sopenharmony_ci}
8949596a2c1Sopenharmony_ci
8959596a2c1Sopenharmony_cistring LocaleConfig::GetDisplayOverrideRegion(const std::string &region, const std::string &displayLocale)
8969596a2c1Sopenharmony_ci{
8979596a2c1Sopenharmony_ci    UErrorCode status = U_ZERO_ERROR;
8989596a2c1Sopenharmony_ci    icu::Locale originLocale;
8999596a2c1Sopenharmony_ci    icu::UnicodeString displayRegion;
9009596a2c1Sopenharmony_ci    if (displayLocale.compare(currentOverrideRegion) != 0) {
9019596a2c1Sopenharmony_ci        std::string xmlPath = REGION_PATH + displayLocale + ".xml";
9029596a2c1Sopenharmony_ci        region2DisplayName.clear();
9039596a2c1Sopenharmony_ci        ReadRegionData(xmlPath.c_str());
9049596a2c1Sopenharmony_ci        currentOverrideRegion = displayLocale;
9059596a2c1Sopenharmony_ci    }
9069596a2c1Sopenharmony_ci    if (region2DisplayName.find(region) != region2DisplayName.end()) {
9079596a2c1Sopenharmony_ci        return region2DisplayName.at(region);
9089596a2c1Sopenharmony_ci    } else {
9099596a2c1Sopenharmony_ci        icu::Locale locale = icu::Locale::forLanguageTag(displayLocale, status);
9109596a2c1Sopenharmony_ci        if (U_FAILURE(status)) {
9119596a2c1Sopenharmony_ci            return "";
9129596a2c1Sopenharmony_ci        }
9139596a2c1Sopenharmony_ci        if (IsValidRegion(region)) {
9149596a2c1Sopenharmony_ci            icu::LocaleBuilder builder = icu::LocaleBuilder().setRegion(region);
9159596a2c1Sopenharmony_ci            originLocale = builder.build(status);
9169596a2c1Sopenharmony_ci        } else {
9179596a2c1Sopenharmony_ci            originLocale = icu::Locale::forLanguageTag(region, status);
9189596a2c1Sopenharmony_ci        }
9199596a2c1Sopenharmony_ci        originLocale.getDisplayCountry(locale, displayRegion);
9209596a2c1Sopenharmony_ci        std::string result;
9219596a2c1Sopenharmony_ci        displayRegion.toUTF8String(result);
9229596a2c1Sopenharmony_ci        return result;
9239596a2c1Sopenharmony_ci    }
9249596a2c1Sopenharmony_ci}
9259596a2c1Sopenharmony_ci
9269596a2c1Sopenharmony_cistring LocaleConfig::GetDisplayRegion(const string &region, const string &displayLocale, bool sentenceCase)
9279596a2c1Sopenharmony_ci{
9289596a2c1Sopenharmony_ci    UErrorCode status = U_ZERO_ERROR;
9299596a2c1Sopenharmony_ci    icu::Locale originLocale;
9309596a2c1Sopenharmony_ci    if (IsValidRegion(region)) {
9319596a2c1Sopenharmony_ci        icu::LocaleBuilder builder = icu::LocaleBuilder().setRegion(region);
9329596a2c1Sopenharmony_ci        originLocale = builder.build(status);
9339596a2c1Sopenharmony_ci    } else {
9349596a2c1Sopenharmony_ci        originLocale = icu::Locale::forLanguageTag(region, status);
9359596a2c1Sopenharmony_ci    }
9369596a2c1Sopenharmony_ci    std::string country(originLocale.getCountry());
9379596a2c1Sopenharmony_ci    if (country.length() == 0) {
9389596a2c1Sopenharmony_ci        return PseudoLocalizationProcessor("");
9399596a2c1Sopenharmony_ci    }
9409596a2c1Sopenharmony_ci    if (U_FAILURE(status)) {
9419596a2c1Sopenharmony_ci        return PseudoLocalizationProcessor("");
9429596a2c1Sopenharmony_ci    }
9439596a2c1Sopenharmony_ci    icu::Locale locale = icu::Locale::forLanguageTag(displayLocale, status);
9449596a2c1Sopenharmony_ci    if (U_FAILURE(status)) {
9459596a2c1Sopenharmony_ci        return PseudoLocalizationProcessor("");
9469596a2c1Sopenharmony_ci    }
9479596a2c1Sopenharmony_ci    icu::UnicodeString unistr;
9489596a2c1Sopenharmony_ci    icu::UnicodeString displayRegion;
9499596a2c1Sopenharmony_ci    std::string result;
9509596a2c1Sopenharmony_ci    if (overrideSupportedRegions.find(displayLocale) != overrideSupportedRegions.end()) {
9519596a2c1Sopenharmony_ci        result = GetDisplayOverrideRegion(region, displayLocale);
9529596a2c1Sopenharmony_ci    } else {
9539596a2c1Sopenharmony_ci        originLocale.getDisplayCountry(locale, displayRegion);
9549596a2c1Sopenharmony_ci        displayRegion.toUTF8String(result);
9559596a2c1Sopenharmony_ci    }
9569596a2c1Sopenharmony_ci    if (sentenceCase) {
9579596a2c1Sopenharmony_ci        char ch = static_cast<char>(toupper(result[0]));
9589596a2c1Sopenharmony_ci        return PseudoLocalizationProcessor(result.replace(0, 1, 1, ch));
9599596a2c1Sopenharmony_ci    }
9609596a2c1Sopenharmony_ci    return PseudoLocalizationProcessor(result);
9619596a2c1Sopenharmony_ci}
9629596a2c1Sopenharmony_ci
9639596a2c1Sopenharmony_cibool LocaleConfig::IsRTL(const string &locale)
9649596a2c1Sopenharmony_ci{
9659596a2c1Sopenharmony_ci    icu::Locale curLocale(locale.c_str());
9669596a2c1Sopenharmony_ci    return curLocale.isRightToLeft();
9679596a2c1Sopenharmony_ci}
9689596a2c1Sopenharmony_ci
9699596a2c1Sopenharmony_civoid parseExtension(const std::string &extension, std::map<std::string, std::string> &map)
9709596a2c1Sopenharmony_ci{
9719596a2c1Sopenharmony_ci    std::string pattern = "-..-";
9729596a2c1Sopenharmony_ci    std::regex express(pattern);
9739596a2c1Sopenharmony_ci
9749596a2c1Sopenharmony_ci    std::regex_token_iterator<std::string::const_iterator> begin1(extension.cbegin(), extension.cend(), express);
9759596a2c1Sopenharmony_ci    std::regex_token_iterator<std::string::const_iterator> begin2(extension.cbegin(), extension.cend(), express, -1);
9769596a2c1Sopenharmony_ci    begin2++;
9779596a2c1Sopenharmony_ci    for (; begin1 != std::sregex_token_iterator() && begin2 != std::sregex_token_iterator(); begin1++, begin2++) {
9789596a2c1Sopenharmony_ci        map.insert(std::pair<std::string, std::string>(begin1->str(), begin2->str()));
9799596a2c1Sopenharmony_ci    }
9809596a2c1Sopenharmony_ci}
9819596a2c1Sopenharmony_ci
9829596a2c1Sopenharmony_civoid setExtension(std::string &extension, const std::string &tag, const std::set<string> &validValue,
9839596a2c1Sopenharmony_ci    const std::map<std::string, std::string> &extensionMap,
9849596a2c1Sopenharmony_ci    const std::map<std::string, std::string> &defaultExtensionMap)
9859596a2c1Sopenharmony_ci{
9869596a2c1Sopenharmony_ci    std::string value;
9879596a2c1Sopenharmony_ci    auto it = extensionMap.find(tag);
9889596a2c1Sopenharmony_ci    if (it != extensionMap.end()) {
9899596a2c1Sopenharmony_ci        value = it->second;
9909596a2c1Sopenharmony_ci        if (validValue.find(value) == validValue.end()) {
9919596a2c1Sopenharmony_ci            return;
9929596a2c1Sopenharmony_ci        } else {
9939596a2c1Sopenharmony_ci            extension += tag;
9949596a2c1Sopenharmony_ci            extension += value;
9959596a2c1Sopenharmony_ci        }
9969596a2c1Sopenharmony_ci    } else {
9979596a2c1Sopenharmony_ci        it = defaultExtensionMap.find(tag);
9989596a2c1Sopenharmony_ci        if (it != defaultExtensionMap.end()) {
9999596a2c1Sopenharmony_ci            value = it->second;
10009596a2c1Sopenharmony_ci            if (validValue.find(value) == validValue.end()) {
10019596a2c1Sopenharmony_ci                return;
10029596a2c1Sopenharmony_ci            } else {
10039596a2c1Sopenharmony_ci                extension += tag;
10049596a2c1Sopenharmony_ci                extension += value;
10059596a2c1Sopenharmony_ci            }
10069596a2c1Sopenharmony_ci        }
10079596a2c1Sopenharmony_ci    }
10089596a2c1Sopenharmony_ci}
10099596a2c1Sopenharmony_ci
10109596a2c1Sopenharmony_civoid setOtherExtension(std::string &extension, std::map<std::string, std::string> &extensionMap,
10119596a2c1Sopenharmony_ci    std::map<std::string, std::string> &defaultExtensionMap)
10129596a2c1Sopenharmony_ci{
10139596a2c1Sopenharmony_ci    std::set<std::string> tags;
10149596a2c1Sopenharmony_ci    tags.insert("-ca-");
10159596a2c1Sopenharmony_ci    tags.insert("-co-");
10169596a2c1Sopenharmony_ci    tags.insert("-kn-");
10179596a2c1Sopenharmony_ci    tags.insert("-kf-");
10189596a2c1Sopenharmony_ci    tags.insert("-nu-");
10199596a2c1Sopenharmony_ci    tags.insert("-hc-");
10209596a2c1Sopenharmony_ci
10219596a2c1Sopenharmony_ci    for (auto it = tags.begin(); it != tags.end(); it++) {
10229596a2c1Sopenharmony_ci        extensionMap.erase(*it);
10239596a2c1Sopenharmony_ci        defaultExtensionMap.erase(*it);
10249596a2c1Sopenharmony_ci    }
10259596a2c1Sopenharmony_ci
10269596a2c1Sopenharmony_ci    for (auto it = defaultExtensionMap.begin(); it != defaultExtensionMap.end(); it++) {
10279596a2c1Sopenharmony_ci        extensionMap.insert(std::pair<std::string, std::string>(it->first, it->second));
10289596a2c1Sopenharmony_ci    }
10299596a2c1Sopenharmony_ci
10309596a2c1Sopenharmony_ci    for (auto it = extensionMap.begin(); it != extensionMap.end(); it++) {
10319596a2c1Sopenharmony_ci        extension += it->first;
10329596a2c1Sopenharmony_ci        extension += it->second;
10339596a2c1Sopenharmony_ci    }
10349596a2c1Sopenharmony_ci}
10359596a2c1Sopenharmony_ci
10369596a2c1Sopenharmony_cistd::string LocaleConfig::GetValidLocale(const std::string &localeTag)
10379596a2c1Sopenharmony_ci{
10389596a2c1Sopenharmony_ci    std::string baseLocale = "";
10399596a2c1Sopenharmony_ci    std::string extension = "";
10409596a2c1Sopenharmony_ci    std::size_t found = localeTag.find("-u-");
10419596a2c1Sopenharmony_ci    baseLocale = localeTag.substr(0, found);
10429596a2c1Sopenharmony_ci    if (found != std::string::npos) {
10439596a2c1Sopenharmony_ci        extension = localeTag.substr(found);
10449596a2c1Sopenharmony_ci    }
10459596a2c1Sopenharmony_ci    std::map<std::string, std::string> extensionMap;
10469596a2c1Sopenharmony_ci    if (extension != "") {
10479596a2c1Sopenharmony_ci        parseExtension(extension, extensionMap);
10489596a2c1Sopenharmony_ci    }
10499596a2c1Sopenharmony_ci
10509596a2c1Sopenharmony_ci    std::string systemLocaleTag = GetSystemLocale();
10519596a2c1Sopenharmony_ci    std::string defaultExtension = "";
10529596a2c1Sopenharmony_ci    found = systemLocaleTag.find("-u-");
10539596a2c1Sopenharmony_ci    if (found != std::string::npos) {
10549596a2c1Sopenharmony_ci        defaultExtension = systemLocaleTag.substr(found);
10559596a2c1Sopenharmony_ci    }
10569596a2c1Sopenharmony_ci    std::map<std::string, std::string> defaultExtensionMap;
10579596a2c1Sopenharmony_ci    if (defaultExtension != "") {
10589596a2c1Sopenharmony_ci        parseExtension(defaultExtension, defaultExtensionMap);
10599596a2c1Sopenharmony_ci    }
10609596a2c1Sopenharmony_ci
10619596a2c1Sopenharmony_ci    std::string ext = "";
10629596a2c1Sopenharmony_ci    setExtension(ext, "-ca-", validCaTag, extensionMap, defaultExtensionMap);
10639596a2c1Sopenharmony_ci    setExtension(ext, "-co-", validCoTag, extensionMap, defaultExtensionMap);
10649596a2c1Sopenharmony_ci    setExtension(ext, "-kn-", validKnTag, extensionMap, defaultExtensionMap);
10659596a2c1Sopenharmony_ci    setExtension(ext, "-kf-", validKfTag, extensionMap, defaultExtensionMap);
10669596a2c1Sopenharmony_ci    setExtension(ext, "-nu-", validNuTag, extensionMap, defaultExtensionMap);
10679596a2c1Sopenharmony_ci    setExtension(ext, "-hc-", validHcTag, extensionMap, defaultExtensionMap);
10689596a2c1Sopenharmony_ci
10699596a2c1Sopenharmony_ci    std::string otherExt = "";
10709596a2c1Sopenharmony_ci    setOtherExtension(otherExt, extensionMap, defaultExtensionMap);
10719596a2c1Sopenharmony_ci    if (ext != "" || otherExt != "") {
10729596a2c1Sopenharmony_ci        return baseLocale + "-u" + ext + otherExt;
10739596a2c1Sopenharmony_ci    } else {
10749596a2c1Sopenharmony_ci        return baseLocale;
10759596a2c1Sopenharmony_ci    }
10769596a2c1Sopenharmony_ci}
10779596a2c1Sopenharmony_ci
10789596a2c1Sopenharmony_cibool LocaleConfig::IsEmpty24HourClock()
10799596a2c1Sopenharmony_ci{
10809596a2c1Sopenharmony_ci    std::string is24Hour = ReadSystemParameter(HOUR_KEY, CONFIG_LEN);
10819596a2c1Sopenharmony_ci    if (is24Hour.compare("default") == 0) {
10829596a2c1Sopenharmony_ci        return true;
10839596a2c1Sopenharmony_ci    }
10849596a2c1Sopenharmony_ci    return false;
10859596a2c1Sopenharmony_ci}
10869596a2c1Sopenharmony_ci
10879596a2c1Sopenharmony_cibool LocaleConfig::Is24HourClock()
10889596a2c1Sopenharmony_ci{
10899596a2c1Sopenharmony_ci    std::string is24Hour = ReadSystemParameter(HOUR_KEY, CONFIG_LEN);
10909596a2c1Sopenharmony_ci    if (is24Hour.compare("default") == 0) {
10919596a2c1Sopenharmony_ci        std::string systemLocale = GetSystemLocale();
10929596a2c1Sopenharmony_ci        return Is24HourLocale(systemLocale);
10939596a2c1Sopenharmony_ci    }
10949596a2c1Sopenharmony_ci    if (is24Hour.compare("true") == 0) {
10959596a2c1Sopenharmony_ci        return true;
10969596a2c1Sopenharmony_ci    }
10979596a2c1Sopenharmony_ci    return false;
10989596a2c1Sopenharmony_ci}
10999596a2c1Sopenharmony_ci
11009596a2c1Sopenharmony_cistd::string LocaleConfig::GetSystemHour()
11019596a2c1Sopenharmony_ci{
11029596a2c1Sopenharmony_ci    bool is24Hour = Is24HourClock();
11039596a2c1Sopenharmony_ci    return is24Hour ? "true" : "false";
11049596a2c1Sopenharmony_ci}
11059596a2c1Sopenharmony_ci
11069596a2c1Sopenharmony_cibool LocaleConfig::Is24HourLocale(const std::string& systemLocale)
11079596a2c1Sopenharmony_ci{
11089596a2c1Sopenharmony_ci    static std::unordered_map<std::string, bool> is24HourLocaleMap;
11099596a2c1Sopenharmony_ci    if (is24HourLocaleMap.find(systemLocale) != is24HourLocaleMap.end()) {
11109596a2c1Sopenharmony_ci        return is24HourLocaleMap[systemLocale];
11119596a2c1Sopenharmony_ci    }
11129596a2c1Sopenharmony_ci    UErrorCode status = U_ZERO_ERROR;
11139596a2c1Sopenharmony_ci    icu::Locale locale = icu::Locale::forLanguageTag(icu::StringPiece(systemLocale), status);
11149596a2c1Sopenharmony_ci    if (U_FAILURE(status)) {
11159596a2c1Sopenharmony_ci        HILOG_INFO_I18N("Is24HourLocale: %{public}s create locale failed", systemLocale.c_str());
11169596a2c1Sopenharmony_ci        return false;
11179596a2c1Sopenharmony_ci    }
11189596a2c1Sopenharmony_ci
11199596a2c1Sopenharmony_ci    icu::UnicodeString formatPattern;
11209596a2c1Sopenharmony_ci    icu::DateFormat* dateFormat = icu::DateFormat::createTimeInstance(icu::DateFormat::EStyle::kLong, locale);
11219596a2c1Sopenharmony_ci    if (dateFormat == nullptr) {
11229596a2c1Sopenharmony_ci        HILOG_INFO_I18N("Is24HourLocale: createTimeInstance failed");
11239596a2c1Sopenharmony_ci        return false;
11249596a2c1Sopenharmony_ci    }
11259596a2c1Sopenharmony_ci    icu::SimpleDateFormat* simDateFormat = static_cast<icu::SimpleDateFormat*>(dateFormat);
11269596a2c1Sopenharmony_ci    if (simDateFormat == nullptr) {
11279596a2c1Sopenharmony_ci        HILOG_INFO_I18N("Is24HourLocale: failed to convert dateFormat");
11289596a2c1Sopenharmony_ci        return false;
11299596a2c1Sopenharmony_ci    }
11309596a2c1Sopenharmony_ci    simDateFormat->toPattern(formatPattern);
11319596a2c1Sopenharmony_ci    delete dateFormat;
11329596a2c1Sopenharmony_ci    std::string pattern;
11339596a2c1Sopenharmony_ci    formatPattern.toUTF8String(pattern);
11349596a2c1Sopenharmony_ci    bool result = HasDesignator(pattern, 'H');
11359596a2c1Sopenharmony_ci    is24HourLocaleMap[systemLocale] = result;
11369596a2c1Sopenharmony_ci    return result;
11379596a2c1Sopenharmony_ci}
11389596a2c1Sopenharmony_ci
11399596a2c1Sopenharmony_cibool LocaleConfig::HasDesignator(const std::string& pattern, const char designator)
11409596a2c1Sopenharmony_ci{
11419596a2c1Sopenharmony_ci    if (pattern.empty()) {
11429596a2c1Sopenharmony_ci        HILOG_INFO_I18N("HasDesignator: pattern is empty");
11439596a2c1Sopenharmony_ci        return false;
11449596a2c1Sopenharmony_ci    }
11459596a2c1Sopenharmony_ci    bool insideQuote = false;
11469596a2c1Sopenharmony_ci    for (const auto& c : pattern) {
11479596a2c1Sopenharmony_ci        if (c == '\'') {
11489596a2c1Sopenharmony_ci            insideQuote = !insideQuote;
11499596a2c1Sopenharmony_ci        } else if (!insideQuote) {
11509596a2c1Sopenharmony_ci            if (c == designator) {
11519596a2c1Sopenharmony_ci                return true;
11529596a2c1Sopenharmony_ci            }
11539596a2c1Sopenharmony_ci        }
11549596a2c1Sopenharmony_ci    }
11559596a2c1Sopenharmony_ci    return false;
11569596a2c1Sopenharmony_ci}
11579596a2c1Sopenharmony_ci
11589596a2c1Sopenharmony_cibool LocaleConfig::GetUsingLocalDigit()
11599596a2c1Sopenharmony_ci{
11609596a2c1Sopenharmony_ci    std::string locale = GetSystemLocale();
11619596a2c1Sopenharmony_ci    LocaleInfo localeInfo(locale);
11629596a2c1Sopenharmony_ci    std::string language = localeInfo.GetLanguage();
11639596a2c1Sopenharmony_ci    if (localDigitMap.find(language) == localDigitMap.end()) {
11649596a2c1Sopenharmony_ci        return false;
11659596a2c1Sopenharmony_ci    }
11669596a2c1Sopenharmony_ci    std::string localNumberSystem = localDigitMap.at(language);
11679596a2c1Sopenharmony_ci    if (localNumberSystem.compare(localeInfo.GetNumberingSystem()) != 0) {
11689596a2c1Sopenharmony_ci        return false;
11699596a2c1Sopenharmony_ci    }
11709596a2c1Sopenharmony_ci    return true;
11719596a2c1Sopenharmony_ci}
11729596a2c1Sopenharmony_ci
11739596a2c1Sopenharmony_cistd::unordered_set<std::string> LocaleConfig::GetBlockedLanguages()
11749596a2c1Sopenharmony_ci{
11759596a2c1Sopenharmony_ci    return blockedLanguages;
11769596a2c1Sopenharmony_ci}
11779596a2c1Sopenharmony_ci
11789596a2c1Sopenharmony_cistd::unordered_set<std::string> LocaleConfig::GetBlockedRegions()
11799596a2c1Sopenharmony_ci{
11809596a2c1Sopenharmony_ci    return blockedRegions;
11819596a2c1Sopenharmony_ci}
11829596a2c1Sopenharmony_ci
11839596a2c1Sopenharmony_cistd::unordered_set<std::string> LocaleConfig::GetLanguageBlockedRegions()
11849596a2c1Sopenharmony_ci{
11859596a2c1Sopenharmony_ci    std::string systemLanguage = LocaleConfig::GetSystemLanguage();
11869596a2c1Sopenharmony_ci    if (blockedLanguageRegions.find(systemLanguage) != blockedLanguageRegions.end()) {
11879596a2c1Sopenharmony_ci        return blockedLanguageRegions[systemLanguage];
11889596a2c1Sopenharmony_ci    }
11899596a2c1Sopenharmony_ci    std::unordered_set<std::string> emptyResult;
11909596a2c1Sopenharmony_ci    return emptyResult;
11919596a2c1Sopenharmony_ci}
11929596a2c1Sopenharmony_ci
11939596a2c1Sopenharmony_ciI18nErrorCode LocaleConfig::SetSystemLanguage(const std::string &languageTag)
11949596a2c1Sopenharmony_ci{
11959596a2c1Sopenharmony_ci    if (!IsValidTag(languageTag)) {
11969596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("LocaleConfig::SetSystemLanguage %{public}s is not valid language tag.",
11979596a2c1Sopenharmony_ci            languageTag.c_str());
11989596a2c1Sopenharmony_ci        return I18nErrorCode::INVALID_LANGUAGE_TAG;
11999596a2c1Sopenharmony_ci    }
12009596a2c1Sopenharmony_ci    // save old language, reset system language to old language if update locale failed.
12019596a2c1Sopenharmony_ci    std::string oldLanguageTag = GetSystemLanguage();
12029596a2c1Sopenharmony_ci    if (SetParameter(LANGUAGE_KEY, languageTag.data()) != 0) {
12039596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("LocaleConfig::SetSystemLanguage update system language failed.");
12049596a2c1Sopenharmony_ci        return I18nErrorCode::UPDATE_SYSTEM_LANGUAGE_FAILED;
12059596a2c1Sopenharmony_ci    }
12069596a2c1Sopenharmony_ci    std::string newLocaleTag = UpdateLanguageOfLocale(languageTag);
12079596a2c1Sopenharmony_ci    if (SetSystemLocale(newLocaleTag) == I18nErrorCode::SUCCESS) {
12089596a2c1Sopenharmony_ci#ifdef SUPPORT_MULTI_USER
12099596a2c1Sopenharmony_ci        MultiUsers::SaveLanguage("", languageTag);
12109596a2c1Sopenharmony_ci#endif
12119596a2c1Sopenharmony_ci        return I18nErrorCode::SUCCESS;
12129596a2c1Sopenharmony_ci    }
12139596a2c1Sopenharmony_ci    // reset system language to old language in case that system language is inconsist with system locale's lanuage.
12149596a2c1Sopenharmony_ci    HILOG_ERROR_I18N("LocaleConfig::SetSystemLanguage update system locale failed.");
12159596a2c1Sopenharmony_ci    SetParameter(LANGUAGE_KEY, oldLanguageTag.data());
12169596a2c1Sopenharmony_ci    return I18nErrorCode::UPDATE_SYSTEM_LANGUAGE_FAILED;
12179596a2c1Sopenharmony_ci}
12189596a2c1Sopenharmony_ci
12199596a2c1Sopenharmony_ciI18nErrorCode LocaleConfig::SetSystemRegion(const std::string &regionTag)
12209596a2c1Sopenharmony_ci{
12219596a2c1Sopenharmony_ci    if (!IsValidRegion(regionTag)) {
12229596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("LocaleConfig::SetSystemRegion %{public}s is not valid region tag.", regionTag.c_str());
12239596a2c1Sopenharmony_ci        return I18nErrorCode::INVALID_REGION_TAG;
12249596a2c1Sopenharmony_ci    }
12259596a2c1Sopenharmony_ci    return SetSystemLocale(UpdateRegionOfLocale(regionTag));
12269596a2c1Sopenharmony_ci}
12279596a2c1Sopenharmony_ci
12289596a2c1Sopenharmony_ciI18nErrorCode LocaleConfig::SetSystemLocale(const std::string &localeTag)
12299596a2c1Sopenharmony_ci{
12309596a2c1Sopenharmony_ci    if (!IsValidTag(localeTag)) {
12319596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("LocaleConfig::SetSystemLocale %{public}s is not a valid locale tag.", localeTag.c_str());
12329596a2c1Sopenharmony_ci        return I18nErrorCode::INVALID_LOCALE_TAG;
12339596a2c1Sopenharmony_ci    }
12349596a2c1Sopenharmony_ci    if (SetParameter(LOCALE_KEY, localeTag.data()) != 0) {
12359596a2c1Sopenharmony_ci        return I18nErrorCode::UPDATE_SYSTEM_LOCALE_FAILED;
12369596a2c1Sopenharmony_ci    }
12379596a2c1Sopenharmony_ci#ifdef SUPPORT_MULTI_USER
12389596a2c1Sopenharmony_ci    MultiUsers::SaveLocale("", localeTag);
12399596a2c1Sopenharmony_ci#endif
12409596a2c1Sopenharmony_ci#ifdef SUPPORT_GRAPHICS
12419596a2c1Sopenharmony_ci    UpdateConfiguration(AAFwk::GlobalConfigurationKey::SYSTEM_LANGUAGE, localeTag);
12429596a2c1Sopenharmony_ci    return PublishCommonEvent(EventFwk::CommonEventSupport::COMMON_EVENT_LOCALE_CHANGED);
12439596a2c1Sopenharmony_ci#else
12449596a2c1Sopenharmony_ci    return I18nErrorCode::SUCCESS;
12459596a2c1Sopenharmony_ci#endif
12469596a2c1Sopenharmony_ci}
12479596a2c1Sopenharmony_ci
12489596a2c1Sopenharmony_cibool LocaleConfig::IsValid24HourClockValue(const std::string &tag)
12499596a2c1Sopenharmony_ci{
12509596a2c1Sopenharmony_ci    if (tag.compare("true") == 0 || tag.compare("false") == 0 || tag.compare("default") == 0) {
12519596a2c1Sopenharmony_ci        return true;
12529596a2c1Sopenharmony_ci    }
12539596a2c1Sopenharmony_ci    return false;
12549596a2c1Sopenharmony_ci}
12559596a2c1Sopenharmony_ci
12569596a2c1Sopenharmony_ciI18nErrorCode LocaleConfig::Set24HourClock(const std::string &option)
12579596a2c1Sopenharmony_ci{
12589596a2c1Sopenharmony_ci    if (!IsValid24HourClockValue(option)) {
12599596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("LocaleConfig::Set24HourClock invalid 24 Hour clock tag: %{public}s", option.c_str());
12609596a2c1Sopenharmony_ci        return I18nErrorCode::INVALID_24_HOUR_CLOCK_TAG;
12619596a2c1Sopenharmony_ci    }
12629596a2c1Sopenharmony_ci    if (SetParameter(HOUR_KEY, option.data()) != 0) {
12639596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("LocaleConfig::Set24HourClock update 24 hour clock failed with option=%{public}s",
12649596a2c1Sopenharmony_ci            option.c_str());
12659596a2c1Sopenharmony_ci        return I18nErrorCode::UPDATE_24_HOUR_CLOCK_FAILED;
12669596a2c1Sopenharmony_ci    }
12679596a2c1Sopenharmony_ci#ifdef SUPPORT_MULTI_USER
12689596a2c1Sopenharmony_ci    MultiUsers::SaveIs24Hour("", option);
12699596a2c1Sopenharmony_ci#endif
12709596a2c1Sopenharmony_ci#ifdef SUPPORT_GRAPHICS
12719596a2c1Sopenharmony_ci    UpdateConfiguration(AAFwk::GlobalConfigurationKey::SYSTEM_HOUR, option);
12729596a2c1Sopenharmony_ci    return PublishCommonEvent(EventFwk::CommonEventSupport::COMMON_EVENT_TIME_CHANGED);
12739596a2c1Sopenharmony_ci#else
12749596a2c1Sopenharmony_ci    return I18nErrorCode::SUCCESS;
12759596a2c1Sopenharmony_ci#endif
12769596a2c1Sopenharmony_ci}
12779596a2c1Sopenharmony_ci
12789596a2c1Sopenharmony_ciI18nErrorCode LocaleConfig::SetUsingLocalDigit(bool flag)
12799596a2c1Sopenharmony_ci{
12809596a2c1Sopenharmony_ci    // check whether current language support local digit.
12819596a2c1Sopenharmony_ci    std::string localeTag = GetSystemLocale();
12829596a2c1Sopenharmony_ci    std::string languageTag = localeTag.substr(0, 2); // obtain 2 length language code.
12839596a2c1Sopenharmony_ci    auto it = localDigitMap.find(languageTag);
12849596a2c1Sopenharmony_ci    if (it == localDigitMap.end()) {
12859596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("LocaleConfig::SetUsingLocalDigit current system doesn't support set local digit");
12869596a2c1Sopenharmony_ci        return I18nErrorCode::UPDATE_LOCAL_DIGIT_FAILED;
12879596a2c1Sopenharmony_ci    }
12889596a2c1Sopenharmony_ci    // update system locale.
12899596a2c1Sopenharmony_ci    return SetSystemLocale(UpdateNumberSystemOfLocale(it->second, flag));
12909596a2c1Sopenharmony_ci}
12919596a2c1Sopenharmony_ci
12929596a2c1Sopenharmony_cistd::string LocaleConfig::UpdateNumberSystemOfLocale(const std::string &localDigitTag, bool flag)
12939596a2c1Sopenharmony_ci{
12949596a2c1Sopenharmony_ci    if (flag) {
12959596a2c1Sopenharmony_ci        // add local digit tag to number system param of locale
12969596a2c1Sopenharmony_ci        return AddLocalDigitToLocale(localDigitTag);
12979596a2c1Sopenharmony_ci    }
12989596a2c1Sopenharmony_ci    // remove local digit tag to number system param of locale
12999596a2c1Sopenharmony_ci    return RemoveLocalDigitFromLocale(localDigitTag);
13009596a2c1Sopenharmony_ci}
13019596a2c1Sopenharmony_ci
13029596a2c1Sopenharmony_cistd::string LocaleConfig::AddLocalDigitToLocale(const std::string &localDigitTag)
13039596a2c1Sopenharmony_ci{
13049596a2c1Sopenharmony_ci    std::string localeTag = GetSystemLocale();
13059596a2c1Sopenharmony_ci    // Case: no extend param, add '-u-' and number system tag.
13069596a2c1Sopenharmony_ci    if (localeTag.find("-u-") == std::string::npos) {
13079596a2c1Sopenharmony_ci        localeTag += "-u" + std::string(NUMBER_SYSTEM_KEY) + localDigitTag;
13089596a2c1Sopenharmony_ci        return localeTag;
13099596a2c1Sopenharmony_ci    }
13109596a2c1Sopenharmony_ci    // Case: has extend param but doesn't hava number system param, add number system tag.
13119596a2c1Sopenharmony_ci    if (localeTag.find(NUMBER_SYSTEM_KEY) == std::string::npos) {
13129596a2c1Sopenharmony_ci        localeTag += std::string(NUMBER_SYSTEM_KEY) + localDigitTag;
13139596a2c1Sopenharmony_ci        return localeTag;
13149596a2c1Sopenharmony_ci    }
13159596a2c1Sopenharmony_ci    // Case: has number system param, replace local digit tag to localDigitTag.
13169596a2c1Sopenharmony_ci    LocaleInfo localeInfo(localeTag);
13179596a2c1Sopenharmony_ci    std::string oldNumberSystem = localeInfo.GetNumberingSystem();
13189596a2c1Sopenharmony_ci    localeTag.replace(localeTag.find(oldNumberSystem), oldNumberSystem.length(), localDigitTag);
13199596a2c1Sopenharmony_ci    return localeTag;
13209596a2c1Sopenharmony_ci}
13219596a2c1Sopenharmony_ci
13229596a2c1Sopenharmony_cistd::string LocaleConfig::RemoveLocalDigitFromLocale(const std::string &localDigitTag)
13239596a2c1Sopenharmony_ci{
13249596a2c1Sopenharmony_ci    // remove number system tag from locale
13259596a2c1Sopenharmony_ci    std::string localeTag = GetSystemLocale();
13269596a2c1Sopenharmony_ci    std::string numberSystemTag = NUMBER_SYSTEM_KEY + localDigitTag;
13279596a2c1Sopenharmony_ci    size_t pos = localeTag.find(numberSystemTag);
13289596a2c1Sopenharmony_ci    if (pos != std::string::npos) {
13299596a2c1Sopenharmony_ci        localeTag.replace(pos, numberSystemTag.length(), "");
13309596a2c1Sopenharmony_ci    }
13319596a2c1Sopenharmony_ci    // remove "-u" if localeTag ends with "-u"
13329596a2c1Sopenharmony_ci    size_t uLength = 2;
13339596a2c1Sopenharmony_ci    if (localeTag.find("-u") == (localeTag.length() - uLength)) {
13349596a2c1Sopenharmony_ci        localeTag.resize(localeTag.length() - uLength);
13359596a2c1Sopenharmony_ci    }
13369596a2c1Sopenharmony_ci    return localeTag;
13379596a2c1Sopenharmony_ci}
13389596a2c1Sopenharmony_ci
13399596a2c1Sopenharmony_ci#ifdef SUPPORT_GRAPHICS
13409596a2c1Sopenharmony_civoid LocaleConfig::UpdateConfiguration(const char *key, const std::string &value)
13419596a2c1Sopenharmony_ci{
13429596a2c1Sopenharmony_ci    AppExecFwk::Configuration configuration;
13439596a2c1Sopenharmony_ci    configuration.AddItem(key, value);
13449596a2c1Sopenharmony_ci    auto appMgrClient = std::make_unique<AppExecFwk::AppMgrClient>();
13459596a2c1Sopenharmony_ci    appMgrClient->UpdateConfiguration(configuration);
13469596a2c1Sopenharmony_ci    HILOG_INFO_I18N("LocaleConfig::UpdateLanguageConfiguration update configuration finished.");
13479596a2c1Sopenharmony_ci}
13489596a2c1Sopenharmony_ci
13499596a2c1Sopenharmony_ciI18nErrorCode LocaleConfig::PublishCommonEvent(const std::string &eventType)
13509596a2c1Sopenharmony_ci{
13519596a2c1Sopenharmony_ci    OHOS::AAFwk::Want localeChangeWant;
13529596a2c1Sopenharmony_ci    localeChangeWant.SetAction(eventType);
13539596a2c1Sopenharmony_ci    OHOS::EventFwk::CommonEventData event(localeChangeWant);
13549596a2c1Sopenharmony_ci    if (!OHOS::EventFwk::CommonEventManager::PublishCommonEvent(event)) {
13559596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("LocaleConfig::PublishCommonEvent Failed to Publish event %{public}s",
13569596a2c1Sopenharmony_ci            localeChangeWant.GetAction().c_str());
13579596a2c1Sopenharmony_ci        return I18nErrorCode::PUBLISH_COMMON_EVENT_FAILED;
13589596a2c1Sopenharmony_ci    }
13599596a2c1Sopenharmony_ci    HILOG_INFO_I18N("LocaleConfig::PublishCommonEvent publish event finished.");
13609596a2c1Sopenharmony_ci    return I18nErrorCode::SUCCESS;
13619596a2c1Sopenharmony_ci}
13629596a2c1Sopenharmony_ci#endif
13639596a2c1Sopenharmony_ci
13649596a2c1Sopenharmony_cistd::string LocaleConfig::UpdateLanguageOfLocale(const std::string &languageTag)
13659596a2c1Sopenharmony_ci{
13669596a2c1Sopenharmony_ci    // Compute language and script part from languageTag.
13679596a2c1Sopenharmony_ci    UErrorCode status = U_ZERO_ERROR;
13689596a2c1Sopenharmony_ci    icu::Locale languageLocale = icu::Locale::forLanguageTag(languageTag.c_str(), status);
13699596a2c1Sopenharmony_ci    if (U_FAILURE(status)) {
13709596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("LocaleConfig::UpdateLanguageOfLocale init icu Locale for language %{public}s failed.",
13719596a2c1Sopenharmony_ci            languageTag.c_str());
13729596a2c1Sopenharmony_ci        return "";
13739596a2c1Sopenharmony_ci    }
13749596a2c1Sopenharmony_ci    std::string langTag = languageLocale.getLanguage();
13759596a2c1Sopenharmony_ci    std::string scriptTag = languageLocale.getScript();
13769596a2c1Sopenharmony_ci    // Compute region and extend param part from current system locale.
13779596a2c1Sopenharmony_ci    std::string systemLocaleTag = GetSystemLocale();
13789596a2c1Sopenharmony_ci    icu::Locale systemLocale = icu::Locale::forLanguageTag(systemLocaleTag.c_str(), status);
13799596a2c1Sopenharmony_ci    if (U_FAILURE(status)) {
13809596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("LocaleConfig::UpdateSystemLocale init icu Locale for locale %{public}s failed.",
13819596a2c1Sopenharmony_ci            systemLocaleTag.c_str());
13829596a2c1Sopenharmony_ci        return "";
13839596a2c1Sopenharmony_ci    }
13849596a2c1Sopenharmony_ci    std::string regionTag = systemLocale.getCountry();
13859596a2c1Sopenharmony_ci    std::string extendParamTag;
13869596a2c1Sopenharmony_ci    size_t pos = systemLocaleTag.find("-u-");
13879596a2c1Sopenharmony_ci    if (pos != std::string::npos) {
13889596a2c1Sopenharmony_ci        extendParamTag = systemLocaleTag.substr(pos);
13899596a2c1Sopenharmony_ci    }
13909596a2c1Sopenharmony_ci    // Combine above elements.
13919596a2c1Sopenharmony_ci    return CreateLocale(langTag, scriptTag, regionTag, extendParamTag);
13929596a2c1Sopenharmony_ci}
13939596a2c1Sopenharmony_ci
13949596a2c1Sopenharmony_cistd::string LocaleConfig::CreateLocale(const std::string &languageTag, const std::string &scriptTag,
13959596a2c1Sopenharmony_ci    const std::string &regionTag, const std::string &extendParamTag)
13969596a2c1Sopenharmony_ci{
13979596a2c1Sopenharmony_ci    // combine language, script, region and extend param with '-'
13989596a2c1Sopenharmony_ci    std::string localeTag = languageTag;
13999596a2c1Sopenharmony_ci    std::string splitor = "-";
14009596a2c1Sopenharmony_ci    if (scriptTag.length() > 0) {
14019596a2c1Sopenharmony_ci        localeTag += splitor + scriptTag;
14029596a2c1Sopenharmony_ci    }
14039596a2c1Sopenharmony_ci    if (regionTag.length() > 0) {
14049596a2c1Sopenharmony_ci        localeTag += splitor + regionTag;
14059596a2c1Sopenharmony_ci    }
14069596a2c1Sopenharmony_ci    if (extendParamTag.length() > 0) {
14079596a2c1Sopenharmony_ci        localeTag += extendParamTag;
14089596a2c1Sopenharmony_ci    }
14099596a2c1Sopenharmony_ci    return localeTag;
14109596a2c1Sopenharmony_ci}
14119596a2c1Sopenharmony_ci
14129596a2c1Sopenharmony_cistd::string LocaleConfig::UpdateRegionOfLocale(const std::string &regionTag)
14139596a2c1Sopenharmony_ci{
14149596a2c1Sopenharmony_ci    std::string localeTag = GetSystemLocale();
14159596a2c1Sopenharmony_ci    // if current system locale is null, contruct a locale from region tag.
14169596a2c1Sopenharmony_ci    if (localeTag.length() == 0) {
14179596a2c1Sopenharmony_ci        return CreateLocaleFromRegion(regionTag);
14189596a2c1Sopenharmony_ci    }
14199596a2c1Sopenharmony_ci    // combine locale with origin locale's language and script with regionTag.
14209596a2c1Sopenharmony_ci    UErrorCode status = U_ZERO_ERROR;
14219596a2c1Sopenharmony_ci    const icu::Locale origin = icu::Locale::forLanguageTag(localeTag, status);
14229596a2c1Sopenharmony_ci    if (U_FAILURE(status)) {
14239596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("LocaleConfig::UpdateRegionOfLocale init origin locale failed.");
14249596a2c1Sopenharmony_ci        return "";
14259596a2c1Sopenharmony_ci    }
14269596a2c1Sopenharmony_ci    icu::LocaleBuilder builder = icu::LocaleBuilder().setLanguage(origin.getLanguage()).
14279596a2c1Sopenharmony_ci        setScript(origin.getScript()).setRegion(regionTag);
14289596a2c1Sopenharmony_ci    icu::Locale temp = builder.setExtension('u', "").build(status);
14299596a2c1Sopenharmony_ci    string ret = temp.toLanguageTag<string>(status);
14309596a2c1Sopenharmony_ci    if (U_FAILURE(status)) {
14319596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("LocaleConfig::UpdateRegionOfLocale obtain new locale's tag failed.");
14329596a2c1Sopenharmony_ci        return "";
14339596a2c1Sopenharmony_ci    }
14349596a2c1Sopenharmony_ci    return ret;
14359596a2c1Sopenharmony_ci}
14369596a2c1Sopenharmony_ci
14379596a2c1Sopenharmony_cistd::string LocaleConfig::CreateLocaleFromRegion(const std::string &regionTag)
14389596a2c1Sopenharmony_ci{
14399596a2c1Sopenharmony_ci    // fill locale with icu
14409596a2c1Sopenharmony_ci    icu::Locale locale("", regionTag.c_str());
14419596a2c1Sopenharmony_ci    UErrorCode status = U_ZERO_ERROR;
14429596a2c1Sopenharmony_ci    locale.addLikelySubtags(status);
14439596a2c1Sopenharmony_ci    if (U_FAILURE(status)) {
14449596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("LocaleConfig::CreateLocaleFromRegion init new locale failed.");
14459596a2c1Sopenharmony_ci        return "";
14469596a2c1Sopenharmony_ci    }
14479596a2c1Sopenharmony_ci    std::string localeTag = locale.toLanguageTag<string>(status);
14489596a2c1Sopenharmony_ci    if (U_FAILURE(status)) {
14499596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("LocaleConfig::CreateLocaleFromRegion obtain new locale's tag failed.");
14509596a2c1Sopenharmony_ci        return "";
14519596a2c1Sopenharmony_ci    }
14529596a2c1Sopenharmony_ci    return localeTag;
14539596a2c1Sopenharmony_ci}
14549596a2c1Sopenharmony_ci
14559596a2c1Sopenharmony_cistd::string LocaleConfig::GetLanguageKey()
14569596a2c1Sopenharmony_ci{
14579596a2c1Sopenharmony_ci    return LANGUAGE_KEY;
14589596a2c1Sopenharmony_ci}
14599596a2c1Sopenharmony_ci
14609596a2c1Sopenharmony_cistd::string LocaleConfig::GetLocaleKey()
14619596a2c1Sopenharmony_ci{
14629596a2c1Sopenharmony_ci    return LOCALE_KEY;
14639596a2c1Sopenharmony_ci}
14649596a2c1Sopenharmony_ci
14659596a2c1Sopenharmony_cistd::string LocaleConfig::GetHourKey()
14669596a2c1Sopenharmony_ci{
14679596a2c1Sopenharmony_ci    return HOUR_KEY;
14689596a2c1Sopenharmony_ci}
14699596a2c1Sopenharmony_ci} // namespace I18n
14709596a2c1Sopenharmony_ci} // namespace Global
14719596a2c1Sopenharmony_ci} // namespace OHOS
1472