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#ifdef SUPPORT_APP_PREFERRED_LANGUAGE 169596a2c1Sopenharmony_ci#include <regex> 179596a2c1Sopenharmony_ci#include "application_context.h" 189596a2c1Sopenharmony_ci#include "bundle_info.h" 199596a2c1Sopenharmony_ci#include "bundle_mgr_interface.h" 209596a2c1Sopenharmony_ci#include "iservice_registry.h" 219596a2c1Sopenharmony_ci#include "system_ability_definition.h" 229596a2c1Sopenharmony_ci#endif 239596a2c1Sopenharmony_ci#include "i18n_hilog.h" 249596a2c1Sopenharmony_ci#include "locale_config.h" 259596a2c1Sopenharmony_ci#include "locale_info.h" 269596a2c1Sopenharmony_ci#include "locale_matcher.h" 279596a2c1Sopenharmony_ci#include "parameter.h" 289596a2c1Sopenharmony_ci#include "preferred_language.h" 299596a2c1Sopenharmony_ci#include "utils.h" 309596a2c1Sopenharmony_ci#include "vector" 319596a2c1Sopenharmony_ci 329596a2c1Sopenharmony_cinamespace OHOS { 339596a2c1Sopenharmony_cinamespace Global { 349596a2c1Sopenharmony_cinamespace I18n { 359596a2c1Sopenharmony_ciconst char *PreferredLanguage::RESOURCE_PATH_HEAD = "/data/accounts/account_0/applications/"; 369596a2c1Sopenharmony_ciconst char *PreferredLanguage::RESOURCE_PATH_TAILOR = "/assets/entry/resources.index"; 379596a2c1Sopenharmony_ciconst char *PreferredLanguage::RESOURCE_PATH_SPLITOR = "/"; 389596a2c1Sopenharmony_ciconst char *PreferredLanguage::PREFERRED_LANGUAGES = "persist.global.preferredLanguages"; 399596a2c1Sopenharmony_ciconst char *PreferredLanguage::APP_LANGUAGE_KEY = "app_language"; 409596a2c1Sopenharmony_ciconst char *PreferredLanguage::I18N_PREFERENCES_FILE_NAME = "/i18n"; 419596a2c1Sopenharmony_ciconst char *PreferredLanguage::DEFAULT_PREFERRED_LANGUAGE = "en-Latn-US"; 429596a2c1Sopenharmony_cistd::vector<std::string> PreferredLanguage::supportLanguageListExt = { "it", "ko", "th", "zz" }; 439596a2c1Sopenharmony_ci 449596a2c1Sopenharmony_cistd::vector<std::string> PreferredLanguage::GetPreferredLanguageList() 459596a2c1Sopenharmony_ci{ 469596a2c1Sopenharmony_ci char preferredLanguageValue[CONFIG_LEN]; 479596a2c1Sopenharmony_ci GetParameter(PREFERRED_LANGUAGES, "", preferredLanguageValue, CONFIG_LEN); 489596a2c1Sopenharmony_ci std::string systemLanguage = GetMatchedLanguage(LocaleConfig::GetSystemLanguage()); 499596a2c1Sopenharmony_ci std::vector<std::string> list; 509596a2c1Sopenharmony_ci Split(preferredLanguageValue, ";", list); 519596a2c1Sopenharmony_ci list = FilterLanguages(list); 529596a2c1Sopenharmony_ci if (!list.size()) { 539596a2c1Sopenharmony_ci if (systemLanguage != "") { 549596a2c1Sopenharmony_ci list.push_back(systemLanguage); 559596a2c1Sopenharmony_ci } 569596a2c1Sopenharmony_ci return list; 579596a2c1Sopenharmony_ci } 589596a2c1Sopenharmony_ci if (list[0] == systemLanguage || systemLanguage == "") { 599596a2c1Sopenharmony_ci return list; 609596a2c1Sopenharmony_ci } 619596a2c1Sopenharmony_ci int systemLanguageIdx = -1; 629596a2c1Sopenharmony_ci for (size_t i = 0; i < list.size(); i++) { 639596a2c1Sopenharmony_ci if (list[i] == systemLanguage) { 649596a2c1Sopenharmony_ci systemLanguageIdx = (int)i; 659596a2c1Sopenharmony_ci } 669596a2c1Sopenharmony_ci } 679596a2c1Sopenharmony_ci if (systemLanguageIdx == -1) { 689596a2c1Sopenharmony_ci list.insert(list.begin(), systemLanguage); 699596a2c1Sopenharmony_ci } else { 709596a2c1Sopenharmony_ci for (size_t i = (size_t)systemLanguageIdx; i > 0; i--) { 719596a2c1Sopenharmony_ci list[i] = list[i - 1]; 729596a2c1Sopenharmony_ci } 739596a2c1Sopenharmony_ci list[0] = systemLanguage; 749596a2c1Sopenharmony_ci } 759596a2c1Sopenharmony_ci return list; 769596a2c1Sopenharmony_ci} 779596a2c1Sopenharmony_ci 789596a2c1Sopenharmony_cistd::vector<std::string> PreferredLanguage::FilterLanguages(std::vector<std::string>& preferredLanguagesList) 799596a2c1Sopenharmony_ci{ 809596a2c1Sopenharmony_ci std::vector<std::string> matchedLanguagesList; 819596a2c1Sopenharmony_ci std::unordered_set<std::string> matchedSet; 829596a2c1Sopenharmony_ci for (auto& preferredLanguage : preferredLanguagesList) { 839596a2c1Sopenharmony_ci std::string matchedLanguage = GetMatchedLanguage(preferredLanguage); 849596a2c1Sopenharmony_ci if (matchedLanguage.empty()) { 859596a2c1Sopenharmony_ci HILOG_ERROR_I18N("FilterLanguages: the matching result of %{public}s is empty.", 869596a2c1Sopenharmony_ci preferredLanguage.c_str()); 879596a2c1Sopenharmony_ci matchedLanguage = DEFAULT_PREFERRED_LANGUAGE; 889596a2c1Sopenharmony_ci } 899596a2c1Sopenharmony_ci if (matchedSet.find(matchedLanguage) == matchedSet.end()) { 909596a2c1Sopenharmony_ci matchedLanguagesList.push_back(matchedLanguage); 919596a2c1Sopenharmony_ci matchedSet.insert(matchedLanguage); 929596a2c1Sopenharmony_ci HILOG_ERROR_I18N("FilterLanguages: the matching result is %{public}s.", matchedLanguage.c_str()); 939596a2c1Sopenharmony_ci } 949596a2c1Sopenharmony_ci } 959596a2c1Sopenharmony_ci return matchedLanguagesList; 969596a2c1Sopenharmony_ci} 979596a2c1Sopenharmony_ci 989596a2c1Sopenharmony_cistd::string PreferredLanguage::GetMatchedLanguage(const std::string& language) 999596a2c1Sopenharmony_ci{ 1009596a2c1Sopenharmony_ci UErrorCode status = U_ZERO_ERROR; 1019596a2c1Sopenharmony_ci icu::Locale locale = icu::Locale::forLanguageTag(language.c_str(), status); 1029596a2c1Sopenharmony_ci if (U_FAILURE(status) || !IsValidLocaleTag(locale)) { 1039596a2c1Sopenharmony_ci HILOG_ERROR_I18N("GetMatchedLanguage: %{public}s is an invalid locale.", language.c_str()); 1049596a2c1Sopenharmony_ci return ""; 1059596a2c1Sopenharmony_ci } 1069596a2c1Sopenharmony_ci LocaleInfo* requestLocale = new LocaleInfo(language); 1079596a2c1Sopenharmony_ci if (requestLocale == nullptr) { 1089596a2c1Sopenharmony_ci HILOG_ERROR_I18N("GetMatchedLanguage: %{public}s failed to construct LocaleInfo.", language.c_str()); 1099596a2c1Sopenharmony_ci return ""; 1109596a2c1Sopenharmony_ci } 1119596a2c1Sopenharmony_ci std::vector<LocaleInfo*> candidateLocales; 1129596a2c1Sopenharmony_ci std::vector<std::string> supportLanguageList; 1139596a2c1Sopenharmony_ci LocaleConfig::GetSystemLanguages(supportLanguageList); 1149596a2c1Sopenharmony_ci supportLanguageList.insert(supportLanguageList.end(), supportLanguageListExt.begin(), 1159596a2c1Sopenharmony_ci supportLanguageListExt.end()); 1169596a2c1Sopenharmony_ci for (auto& supportLanguage : supportLanguageList) { 1179596a2c1Sopenharmony_ci LocaleInfo* supportLocaleInfo = new LocaleInfo(supportLanguage); 1189596a2c1Sopenharmony_ci if (supportLocaleInfo == nullptr) { 1199596a2c1Sopenharmony_ci HILOG_ERROR_I18N("GetMatchedLanguage: %{public}s failed to construct LocaleInfo.", 1209596a2c1Sopenharmony_ci supportLanguage.c_str()); 1219596a2c1Sopenharmony_ci continue; 1229596a2c1Sopenharmony_ci } 1239596a2c1Sopenharmony_ci if (LocaleMatcher::Match(requestLocale, supportLocaleInfo)) { 1249596a2c1Sopenharmony_ci candidateLocales.push_back(supportLocaleInfo); 1259596a2c1Sopenharmony_ci } else { 1269596a2c1Sopenharmony_ci delete supportLocaleInfo; 1279596a2c1Sopenharmony_ci } 1289596a2c1Sopenharmony_ci } 1299596a2c1Sopenharmony_ci std::string matchedLanguage = LocaleMatcher::GetBestMatchedLocale(requestLocale, candidateLocales); 1309596a2c1Sopenharmony_ci for (LocaleInfo* supportLocaleInfo : candidateLocales) { 1319596a2c1Sopenharmony_ci delete supportLocaleInfo; 1329596a2c1Sopenharmony_ci } 1339596a2c1Sopenharmony_ci delete requestLocale; 1349596a2c1Sopenharmony_ci return matchedLanguage; 1359596a2c1Sopenharmony_ci} 1369596a2c1Sopenharmony_ci 1379596a2c1Sopenharmony_cistd::string PreferredLanguage::GetFirstPreferredLanguage() 1389596a2c1Sopenharmony_ci{ 1399596a2c1Sopenharmony_ci std::vector<std::string> preferredLanguageList = GetPreferredLanguageList(); 1409596a2c1Sopenharmony_ci return preferredLanguageList[0]; 1419596a2c1Sopenharmony_ci} 1429596a2c1Sopenharmony_ci 1439596a2c1Sopenharmony_ci#ifdef SUPPORT_APP_PREFERRED_LANGUAGE 1449596a2c1Sopenharmony_cistd::shared_ptr<NativePreferences::Preferences> PreferredLanguage::GetI18nAppPreferences() 1459596a2c1Sopenharmony_ci{ 1469596a2c1Sopenharmony_ci std::shared_ptr<AbilityRuntime::ApplicationContext> appContext = AbilityRuntime::ApplicationContext::GetInstance(); 1479596a2c1Sopenharmony_ci std::string preferencesDirPath = appContext->GetPreferencesDir(); 1489596a2c1Sopenharmony_ci std::string i18nPreferencesFilePath = preferencesDirPath + I18N_PREFERENCES_FILE_NAME; 1499596a2c1Sopenharmony_ci int status; 1509596a2c1Sopenharmony_ci NativePreferences::Options options(i18nPreferencesFilePath); 1519596a2c1Sopenharmony_ci std::shared_ptr<NativePreferences::Preferences> preferences = 1529596a2c1Sopenharmony_ci NativePreferences::PreferencesHelper::GetPreferences(options, status); 1539596a2c1Sopenharmony_ci if (status != 0) { 1549596a2c1Sopenharmony_ci HILOG_ERROR_I18N("PreferredLanguage::GetAppPreferredLanguage get i18n app preferences failed."); 1559596a2c1Sopenharmony_ci return nullptr; 1569596a2c1Sopenharmony_ci } 1579596a2c1Sopenharmony_ci return preferences; 1589596a2c1Sopenharmony_ci} 1599596a2c1Sopenharmony_ci 1609596a2c1Sopenharmony_cibool PreferredLanguage::IsSetAppPreferredLanguage() 1619596a2c1Sopenharmony_ci{ 1629596a2c1Sopenharmony_ci std::shared_ptr<NativePreferences::Preferences> preferences = GetI18nAppPreferences(); 1639596a2c1Sopenharmony_ci if (preferences == nullptr) { 1649596a2c1Sopenharmony_ci HILOG_ERROR_I18N( 1659596a2c1Sopenharmony_ci "PreferredLanguage::IsSetAppPreferredLanguage get i18n preferences failed, return system language."); 1669596a2c1Sopenharmony_ci return false; 1679596a2c1Sopenharmony_ci } 1689596a2c1Sopenharmony_ci std::string res = preferences->GetString(PreferredLanguage::APP_LANGUAGE_KEY, ""); 1699596a2c1Sopenharmony_ci if (res.length() == 0 || res.compare("default") == 0) { 1709596a2c1Sopenharmony_ci return false; 1719596a2c1Sopenharmony_ci } 1729596a2c1Sopenharmony_ci return true; 1739596a2c1Sopenharmony_ci} 1749596a2c1Sopenharmony_ci 1759596a2c1Sopenharmony_cistd::string PreferredLanguage::GetAppPreferredLanguage() 1769596a2c1Sopenharmony_ci{ 1779596a2c1Sopenharmony_ci std::shared_ptr<NativePreferences::Preferences> preferences = GetI18nAppPreferences(); 1789596a2c1Sopenharmony_ci if (preferences == nullptr) { 1799596a2c1Sopenharmony_ci HILOG_ERROR_I18N( 1809596a2c1Sopenharmony_ci "PreferredLanguage::GetAppPreferredLanguage get i18n preferences failed, return system language."); 1819596a2c1Sopenharmony_ci return LocaleConfig::GetSystemLocale(); 1829596a2c1Sopenharmony_ci } 1839596a2c1Sopenharmony_ci std::string res = preferences->GetString(PreferredLanguage::APP_LANGUAGE_KEY, ""); 1849596a2c1Sopenharmony_ci if (res.length() == 0 || res.compare("default") == 0) { 1859596a2c1Sopenharmony_ci return LocaleConfig::GetSystemLocale(); 1869596a2c1Sopenharmony_ci } 1879596a2c1Sopenharmony_ci return res; 1889596a2c1Sopenharmony_ci} 1899596a2c1Sopenharmony_ci 1909596a2c1Sopenharmony_civoid PreferredLanguage::SetAppPreferredLanguage(const std::string &language, I18nErrorCode &errCode) 1919596a2c1Sopenharmony_ci{ 1929596a2c1Sopenharmony_ci std::shared_ptr<AbilityRuntime::ApplicationContext> appContext = AbilityRuntime::ApplicationContext::GetInstance(); 1939596a2c1Sopenharmony_ci if (language.compare("default") != 0) { 1949596a2c1Sopenharmony_ci appContext->SetLanguage(language); 1959596a2c1Sopenharmony_ci } 1969596a2c1Sopenharmony_ci std::shared_ptr<NativePreferences::Preferences> preferences = GetI18nAppPreferences(); 1979596a2c1Sopenharmony_ci if (preferences == nullptr) { 1989596a2c1Sopenharmony_ci errCode = I18nErrorCode::FAILED; 1999596a2c1Sopenharmony_ci HILOG_ERROR_I18N("PreferredLanguage::SetAppPreferredLanguage get i18n preferences failed."); 2009596a2c1Sopenharmony_ci return; 2019596a2c1Sopenharmony_ci } 2029596a2c1Sopenharmony_ci int32_t status = preferences->PutString(PreferredLanguage::APP_LANGUAGE_KEY, language); 2039596a2c1Sopenharmony_ci if (status != 0) { 2049596a2c1Sopenharmony_ci errCode = I18nErrorCode::FAILED; 2059596a2c1Sopenharmony_ci HILOG_ERROR_I18N( 2069596a2c1Sopenharmony_ci "PreferredLanguage::SetAppPreferredLanguage set app language to i18n preferences failed."); 2079596a2c1Sopenharmony_ci return; 2089596a2c1Sopenharmony_ci } 2099596a2c1Sopenharmony_ci preferences->Flush(); 2109596a2c1Sopenharmony_ci} 2119596a2c1Sopenharmony_ci#endif 2129596a2c1Sopenharmony_ci 2139596a2c1Sopenharmony_cistd::string PreferredLanguage::GetPreferredLocale() 2149596a2c1Sopenharmony_ci{ 2159596a2c1Sopenharmony_ci std::string systemLocale = LocaleConfig::GetSystemLocale(); 2169596a2c1Sopenharmony_ci LocaleInfo systemLocaleInfo(systemLocale); 2179596a2c1Sopenharmony_ci std::string systemRegion = systemLocaleInfo.GetRegion(); 2189596a2c1Sopenharmony_ci std::string preferredLanguageLocale = GetFirstPreferredLanguage(); 2199596a2c1Sopenharmony_ci LocaleInfo preferredLanguageLocaleInfo(preferredLanguageLocale); 2209596a2c1Sopenharmony_ci std::string preferredLanguage = preferredLanguageLocaleInfo.GetLanguage(); 2219596a2c1Sopenharmony_ci std::string preferredLocale = preferredLanguage + "-" + systemRegion; 2229596a2c1Sopenharmony_ci return preferredLocale; 2239596a2c1Sopenharmony_ci} 2249596a2c1Sopenharmony_ci 2259596a2c1Sopenharmony_cibool PreferredLanguage::IsValidLanguage(const std::string &language) 2269596a2c1Sopenharmony_ci{ 2279596a2c1Sopenharmony_ci std::string::size_type size = language.size(); 2289596a2c1Sopenharmony_ci if ((size != LANGUAGE_LEN) && (size != LANGUAGE_LEN + 1)) { 2299596a2c1Sopenharmony_ci return false; 2309596a2c1Sopenharmony_ci } 2319596a2c1Sopenharmony_ci for (size_t i = 0; i < size; ++i) { 2329596a2c1Sopenharmony_ci if ((language[i] > 'z') || (language[i] < 'a')) { 2339596a2c1Sopenharmony_ci return false; 2349596a2c1Sopenharmony_ci } 2359596a2c1Sopenharmony_ci } 2369596a2c1Sopenharmony_ci return true; 2379596a2c1Sopenharmony_ci} 2389596a2c1Sopenharmony_ci 2399596a2c1Sopenharmony_cibool PreferredLanguage::IsValidTag(const std::string &tag) 2409596a2c1Sopenharmony_ci{ 2419596a2c1Sopenharmony_ci if (!tag.size()) { 2429596a2c1Sopenharmony_ci return false; 2439596a2c1Sopenharmony_ci } 2449596a2c1Sopenharmony_ci std::vector<std::string> splits; 2459596a2c1Sopenharmony_ci Split(tag, "-", splits); 2469596a2c1Sopenharmony_ci if (!IsValidLanguage(splits[0])) { 2479596a2c1Sopenharmony_ci return false; 2489596a2c1Sopenharmony_ci } 2499596a2c1Sopenharmony_ci return true; 2509596a2c1Sopenharmony_ci} 2519596a2c1Sopenharmony_ci 2529596a2c1Sopenharmony_civoid PreferredLanguage::Split(const std::string &src, const std::string &sep, std::vector<std::string> &dest) 2539596a2c1Sopenharmony_ci{ 2549596a2c1Sopenharmony_ci std::string::size_type begin = 0; 2559596a2c1Sopenharmony_ci std::string::size_type end = src.find(sep); 2569596a2c1Sopenharmony_ci while (end != std::string::npos) { 2579596a2c1Sopenharmony_ci dest.push_back(src.substr(begin, end - begin)); 2589596a2c1Sopenharmony_ci begin = end + sep.size(); 2599596a2c1Sopenharmony_ci end = src.find(sep, begin); 2609596a2c1Sopenharmony_ci } 2619596a2c1Sopenharmony_ci if (begin != src.size()) { 2629596a2c1Sopenharmony_ci dest.push_back(src.substr(begin)); 2639596a2c1Sopenharmony_ci } 2649596a2c1Sopenharmony_ci} 2659596a2c1Sopenharmony_ci 2669596a2c1Sopenharmony_ciI18nErrorCode PreferredLanguage::AddPreferredLanguage(const std::string &language, int32_t index) 2679596a2c1Sopenharmony_ci{ 2689596a2c1Sopenharmony_ci if (!IsValidTag(language)) { 2699596a2c1Sopenharmony_ci HILOG_ERROR_I18N("PreferredLanguage::AddPreferredLanguage %{public}s is not valid language tag.", 2709596a2c1Sopenharmony_ci language.c_str()); 2719596a2c1Sopenharmony_ci return I18nErrorCode::INVALID_LANGUAGE_TAG; 2729596a2c1Sopenharmony_ci } 2739596a2c1Sopenharmony_ci std::vector<std::string> preferredLanguages; 2749596a2c1Sopenharmony_ci I18nErrorCode status = I18nErrorCode::SUCCESS; 2759596a2c1Sopenharmony_ci if (FindLanguage(language) == -1) { 2769596a2c1Sopenharmony_ci // Case: language not in current preferred language list. 2779596a2c1Sopenharmony_ci AddNonExistPreferredLanguage(language, index, preferredLanguages, status); 2789596a2c1Sopenharmony_ci } else { 2799596a2c1Sopenharmony_ci // Case: language in current preferred language list. 2809596a2c1Sopenharmony_ci AddExistPreferredLanguage(language, index, preferredLanguages, status); 2819596a2c1Sopenharmony_ci } 2829596a2c1Sopenharmony_ci if (status != I18nErrorCode::SUCCESS) { 2839596a2c1Sopenharmony_ci HILOG_ERROR_I18N("PreferredLanguage::AddPreferredLanguage failed."); 2849596a2c1Sopenharmony_ci return status; 2859596a2c1Sopenharmony_ci } 2869596a2c1Sopenharmony_ci return SetPreferredLanguages(JoinPreferredLanguages(preferredLanguages)); 2879596a2c1Sopenharmony_ci} 2889596a2c1Sopenharmony_ci 2899596a2c1Sopenharmony_ciI18nErrorCode PreferredLanguage::RemovePreferredLanguage(int32_t index) 2909596a2c1Sopenharmony_ci{ 2919596a2c1Sopenharmony_ci std::vector<std::string> preferredLanguages = GetPreferredLanguageList(); 2929596a2c1Sopenharmony_ci if (preferredLanguages.size() == 1) { 2939596a2c1Sopenharmony_ci HILOG_ERROR_I18N("PreferredLanguage::RemovePreferredLanguage can't remove the only language."); 2949596a2c1Sopenharmony_ci return I18nErrorCode::REMOVE_PREFERRED_LANGUAGE_FAILED; 2959596a2c1Sopenharmony_ci } 2969596a2c1Sopenharmony_ci // valid index is [0, preferredLanguages.size() - 1] for Remove 2979596a2c1Sopenharmony_ci int32_t validIndex = NormalizeIndex(index, preferredLanguages.size() - 1); 2989596a2c1Sopenharmony_ci preferredLanguages.erase(preferredLanguages.begin() + validIndex); 2999596a2c1Sopenharmony_ci // The first language in preferred language list is system language, therefor when first language changed 3009596a2c1Sopenharmony_ci // in preferred language list, we need to reset system language. 3019596a2c1Sopenharmony_ci if (validIndex == 0) { 3029596a2c1Sopenharmony_ci if (LocaleConfig::SetSystemLanguage(preferredLanguages[0]) != I18nErrorCode::SUCCESS) { 3039596a2c1Sopenharmony_ci HILOG_ERROR_I18N("PreferredLanguage::RemovePreferredLanguage update system language failed."); 3049596a2c1Sopenharmony_ci return I18nErrorCode::REMOVE_PREFERRED_LANGUAGE_FAILED; 3059596a2c1Sopenharmony_ci } 3069596a2c1Sopenharmony_ci } 3079596a2c1Sopenharmony_ci return SetPreferredLanguages(JoinPreferredLanguages(preferredLanguages)); 3089596a2c1Sopenharmony_ci} 3099596a2c1Sopenharmony_ci 3109596a2c1Sopenharmony_civoid PreferredLanguage::AddNonExistPreferredLanguage(const std::string& language, int32_t index, 3119596a2c1Sopenharmony_ci std::vector<std::string> &preferredLanguages, I18nErrorCode &errCode) 3129596a2c1Sopenharmony_ci{ 3139596a2c1Sopenharmony_ci // valid index is [0, GetPreferredLanguageList().size()] for add non-exist language. 3149596a2c1Sopenharmony_ci int32_t validIndex = NormalizeIndex(index, GetPreferredLanguageList().size()); 3159596a2c1Sopenharmony_ci preferredLanguages = GetPreferredLanguageList(); 3169596a2c1Sopenharmony_ci preferredLanguages.insert(preferredLanguages.begin() + validIndex, language); 3179596a2c1Sopenharmony_ci // The first language in preferred language list is system language, therefor when first language changed 3189596a2c1Sopenharmony_ci // in preferred language list, we need to reset system language. 3199596a2c1Sopenharmony_ci if (validIndex == 0) { 3209596a2c1Sopenharmony_ci if (LocaleConfig::SetSystemLanguage(preferredLanguages[0]) != I18nErrorCode::SUCCESS) { 3219596a2c1Sopenharmony_ci HILOG_ERROR_I18N("PreferredLanguage::AddNonExistPreferredLanguage update system language failed."); 3229596a2c1Sopenharmony_ci errCode = I18nErrorCode::ADD_PREFERRED_LANGUAGE_NON_EXIST_FAILED; 3239596a2c1Sopenharmony_ci return; 3249596a2c1Sopenharmony_ci } 3259596a2c1Sopenharmony_ci } 3269596a2c1Sopenharmony_ci errCode = I18nErrorCode::SUCCESS; 3279596a2c1Sopenharmony_ci} 3289596a2c1Sopenharmony_ci 3299596a2c1Sopenharmony_civoid PreferredLanguage::AddExistPreferredLanguage(const std::string& language, int32_t index, 3309596a2c1Sopenharmony_ci std::vector<std::string> &preferredLanguages, I18nErrorCode &errCode) 3319596a2c1Sopenharmony_ci{ 3329596a2c1Sopenharmony_ci // throw error when current index is same with target index. 3339596a2c1Sopenharmony_ci // valid index is [0, GetPreferredLanguageList().size() - 1] for add exist language. 3349596a2c1Sopenharmony_ci int32_t validIndex = NormalizeIndex(index, GetPreferredLanguageList().size() - 1); 3359596a2c1Sopenharmony_ci int32_t languageIdx = FindLanguage(language); 3369596a2c1Sopenharmony_ci if (languageIdx == validIndex) { 3379596a2c1Sopenharmony_ci errCode = I18nErrorCode::ADD_PREFERRED_LANGUAGE_EXIST_FAILED; 3389596a2c1Sopenharmony_ci return; 3399596a2c1Sopenharmony_ci } 3409596a2c1Sopenharmony_ci // Move language from languageIdx to validIdx. 3419596a2c1Sopenharmony_ci preferredLanguages = GetPreferredLanguageList(); 3429596a2c1Sopenharmony_ci preferredLanguages.erase(preferredLanguages.begin() + languageIdx); 3439596a2c1Sopenharmony_ci preferredLanguages.insert(preferredLanguages.begin() + validIndex, language); 3449596a2c1Sopenharmony_ci // The first language in preferred language list is system language, therefor when first language changed 3459596a2c1Sopenharmony_ci // in preferred language list, we need to reset system language. 3469596a2c1Sopenharmony_ci if (languageIdx == 0 || validIndex == 0) { 3479596a2c1Sopenharmony_ci if (LocaleConfig::SetSystemLanguage(preferredLanguages[0]) != I18nErrorCode::SUCCESS) { 3489596a2c1Sopenharmony_ci HILOG_ERROR_I18N("PreferredLanguage::AddExistPreferredLanguage update system language failed."); 3499596a2c1Sopenharmony_ci errCode = I18nErrorCode::ADD_PREFERRED_LANGUAGE_EXIST_FAILED; 3509596a2c1Sopenharmony_ci return; 3519596a2c1Sopenharmony_ci } 3529596a2c1Sopenharmony_ci } 3539596a2c1Sopenharmony_ci errCode = I18nErrorCode::SUCCESS; 3549596a2c1Sopenharmony_ci} 3559596a2c1Sopenharmony_ci 3569596a2c1Sopenharmony_ciint32_t PreferredLanguage::NormalizeIndex(int32_t index, int32_t max) 3579596a2c1Sopenharmony_ci{ 3589596a2c1Sopenharmony_ci if (index <= 0) { 3599596a2c1Sopenharmony_ci return 0; 3609596a2c1Sopenharmony_ci } 3619596a2c1Sopenharmony_ci if (index >= max) { 3629596a2c1Sopenharmony_ci return max; 3639596a2c1Sopenharmony_ci } 3649596a2c1Sopenharmony_ci return index; 3659596a2c1Sopenharmony_ci} 3669596a2c1Sopenharmony_ci 3679596a2c1Sopenharmony_ci// Query the index of language in system preferred language list. 3689596a2c1Sopenharmony_ciint32_t PreferredLanguage::FindLanguage(const std::string &language) 3699596a2c1Sopenharmony_ci{ 3709596a2c1Sopenharmony_ci std::vector<std::string> preferredLanguageList = GetPreferredLanguageList(); 3719596a2c1Sopenharmony_ci for (size_t i = 0; i < preferredLanguageList.size(); ++i) { 3729596a2c1Sopenharmony_ci if (preferredLanguageList[i] == language) { 3739596a2c1Sopenharmony_ci return static_cast<int32_t>(i); 3749596a2c1Sopenharmony_ci } 3759596a2c1Sopenharmony_ci } 3769596a2c1Sopenharmony_ci return -1; 3779596a2c1Sopenharmony_ci} 3789596a2c1Sopenharmony_ci 3799596a2c1Sopenharmony_ci// Join preferred language tags to string with ';' 3809596a2c1Sopenharmony_cistd::string PreferredLanguage::JoinPreferredLanguages(const std::vector<std::string> preferredLanguages) 3819596a2c1Sopenharmony_ci{ 3829596a2c1Sopenharmony_ci std::string result = ""; 3839596a2c1Sopenharmony_ci for (size_t i = 0; i < preferredLanguages.size(); ++i) { 3849596a2c1Sopenharmony_ci result += preferredLanguages[i]; 3859596a2c1Sopenharmony_ci result += ";"; 3869596a2c1Sopenharmony_ci } 3879596a2c1Sopenharmony_ci // delete the last ';' 3889596a2c1Sopenharmony_ci result.pop_back(); 3899596a2c1Sopenharmony_ci return result; 3909596a2c1Sopenharmony_ci} 3919596a2c1Sopenharmony_ci 3929596a2c1Sopenharmony_ci// Set PREFERRED_LANGUAGES system parameter with preferredLanguages. 3939596a2c1Sopenharmony_ciI18nErrorCode PreferredLanguage::SetPreferredLanguages(const std::string &preferredLanguages) 3949596a2c1Sopenharmony_ci{ 3959596a2c1Sopenharmony_ci // System parameter value's length can't beyong CONFIG_LEN 3969596a2c1Sopenharmony_ci if (preferredLanguages.length() > CONFIG_LEN) { 3979596a2c1Sopenharmony_ci HILOG_ERROR_I18N("PreferredLanguage::SetPreferredLanguage preferred language list is too long."); 3989596a2c1Sopenharmony_ci return I18nErrorCode::UPDATE_SYSTEM_PREFERRED_LANGUAGE_FAILED; 3999596a2c1Sopenharmony_ci } 4009596a2c1Sopenharmony_ci if (SetParameter(PREFERRED_LANGUAGES, preferredLanguages.data()) != 0) { 4019596a2c1Sopenharmony_ci HILOG_ERROR_I18N("PreferredLanguage::AddPreferredLanguage udpate preferred language param failed."); 4029596a2c1Sopenharmony_ci return I18nErrorCode::UPDATE_SYSTEM_PREFERRED_LANGUAGE_FAILED; 4039596a2c1Sopenharmony_ci } 4049596a2c1Sopenharmony_ci return I18nErrorCode::SUCCESS; 4059596a2c1Sopenharmony_ci} 4069596a2c1Sopenharmony_ci} // namespace I18n 4079596a2c1Sopenharmony_ci} // namespace Global 4089596a2c1Sopenharmony_ci} // namespace OHOS