1 /*
2 * Copyright (c) 2021-2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "locale_config.h"
16 #include "locale_config_ext.h"
17
18 #include <algorithm>
19 #include <regex>
20 #include "accesstoken_kit.h"
21 #ifdef SUPPORT_GRAPHICS
22 #include "app_mgr_client.h"
23 #include "ability_manager_client.h"
24 #include "configuration.h"
25 #include <common_event_data.h>
26 #include <common_event_manager.h>
27 #include <common_event_publish_info.h>
28 #include <common_event_support.h>
29 #endif
30 #include <cctype>
31 #include "config_policy_utils.h"
32 #include "i18n_hilog.h"
33 #include "date_time_format.h"
34 #include "ipc_skeleton.h"
35 #include "libxml/parser.h"
36 #include "locale_info.h"
37 #include "locale_matcher.h"
38 #include "multi_users.h"
39 #include "number_format.h"
40 #include "unicode/dcfmtsym.h"
41 #include "unicode/localebuilder.h"
42 #include "unicode/locdspnm.h"
43 #include "unicode/locid.h"
44 #include <unicode/numsys.h>
45 #include "unicode/smpdtfmt.h"
46 #include "ohos/init_data.h"
47 #include "parameter.h"
48 #include "securec.h"
49 #include "string_ex.h"
50 #include "ucase.h"
51 #include "ulocimp.h"
52 #include "unicode/ulocdata.h"
53 #include "unicode/unistr.h"
54 #include "ureslocs.h"
55 #include "unicode/ustring.h"
56 #include "ustr_imp.h"
57 #include "utils.h"
58 #include "tokenid_kit.h"
59
60 namespace OHOS {
61 namespace Global {
62 namespace I18n {
63 using namespace std;
64 const std::string LocaleConfig::LANGUAGE_KEY = "persist.global.language";
65 const std::string LocaleConfig::LOCALE_KEY = "persist.global.locale";
66 const std::string LocaleConfig::HOUR_KEY = "persist.global.is24Hour";
67 const std::string LocaleConfig::HOUR_EVENT_DATA = "24HourChange";
68 const char *LocaleConfig::UPGRADE_LOCALE_KEY = "persist.global.upgrade_locale";
69 const char *LocaleConfig::DEFAULT_LOCALE_KEY = "const.global.locale";
70 const char *LocaleConfig::DEFAULT_LANGUAGE_KEY = "const.global.language";
71 const char *LocaleConfig::DEFAULT_REGION_KEY = "const.global.region";
72 const char *LocaleConfig::DEVELOPER_MODE_KEY = "const.security.developermode.state";
73 const char *LocaleConfig::SIM_COUNTRY_CODE_KEY = "telephony.sim.countryCode0";
74 const char *LocaleConfig::SUPPORTED_LOCALES_NAME = "supported_locales";
75 const char *LocaleConfig::REGIONS_LANGUAGES_PATH = "etc/xml/i18n_param_config.xml";
76 const char *LocaleConfig::REGIONS_LANGUAGES_NAME = "i18n_param_config";
77 const char *LocaleConfig::SUPPORTED_REGIONS_NAME = "supported_regions";
78 const char *LocaleConfig::WHITE_LANGUAGES_NAME = "white_languages";
79 const char *LocaleConfig::SUPPORTED_LOCALES_PATH = "/system/usr/ohos_locale_config/supported_locales.xml";
80 const char *LocaleConfig::SUPPORTED_LOCALES_OLD_PATH = "/system/usr/ohos_locale_config/supported_locales_old.xml";
81 const char *LocaleConfig::SUPPORT_LOCALES_PATH = "/etc/ohos_lang_config/supported_locales.xml";
82 const char *LocaleConfig::SUPPORT_LOCALES_NAME = "supported_locales";
83 const char *LocaleConfig::DIALECT_LANGS_PATH = "/system/usr/ohos_locale_config/dialect_languages.xml";
84 const char *LocaleConfig::DIALECT_LANGS_NAME = "dialect_langs";
85 const char *LocaleConfig::OVERRIDE_SUPPORTED_REGIONS_NAME = "supported_regions";
86 const char *LocaleConfig::OVERRIDE_SUPPORTED_REGIONS_PATH =
87 "/system/usr/ohos_locale_config/region/supported_regions.xml";
88 const char *LocaleConfig::DEFAULT_LOCALE = "en-Latn";
89 const char *LocaleConfig::supportLocalesTag = "supported_locales";
90 const char *LocaleConfig::LANG_PATH = "/etc/ohos_lang_config/";
91 const char *LocaleConfig::REGION_PATH = "/system/usr/ohos_locale_config/region/";
92 const char *LocaleConfig::rootTag = "languages";
93 const char *LocaleConfig::secondRootTag = "lang";
94 const char *LocaleConfig::rootRegion = "regions";
95 const char *LocaleConfig::secondRootRegion = "region";
96 const std::string LocaleConfig::STANDARD_EXT_PARAM_KEY = "-u-";
97 const std::string LocaleConfig::CUST_EXT_PARAM_KEY = "-x-";
98 const std::string LocaleConfig::NUMBER_SYSTEM_KEY = "nu";
99 const std::string LocaleConfig::TEMPERATURE_UNIT_KEY = "mu";
100 const std::string LocaleConfig::WEEK_DAY_KEY = "fw";
101 const std::string LocaleConfig::CASE_FIRST_KEY = "kf";
102 const std::string LocaleConfig::COLLATION_KEY = "co";
103 const std::string LocaleConfig::NUNBER_PATTERN_KEY = "np";
104 const std::string LocaleConfig::MEASUREMENT_KEY = "ms";
105 const std::string LocaleConfig::NUMERIC_DATE_KEY = "nl";
106 const std::string LocaleConfig::TIMEZONE_KEY = "persist.time.timezone";
107 const std::string LocaleConfig::DEFAULT_TIMEZONE = "GMT";
108 const std::string LocaleConfig::DEFAULT_NUMBERING_SYSTEM_NAME = "latn";
109 unordered_set<string> LocaleConfig::supportedLocales;
110 unordered_set<string> LocaleConfig::supportedLocalesV15;
111 unordered_set<string> LocaleConfig::supportLocales;
112 unordered_set<string> LocaleConfig::supportedRegions;
113 unordered_set<string> LocaleConfig::overrideSupportedRegions;
114 unordered_set<string> LocaleConfig::dialectLang;
115 unordered_set<string> LocaleConfig::whiteLanguages;
116 std::set<std::string> LocaleConfig::extendWhiteLanguageList;
117 std::set<std::string> LocaleConfig::extendWhiteLanguageListV15;
118 unordered_map<string, string> LocaleConfig::dialectMap {
119 { "es-Latn-419", "es-Latn-419" },
120 { "es-Latn-BO", "es-Latn-419" },
121 { "es-Latn-BR", "es-Latn-419" },
122 { "es-Latn-BZ", "es-Latn-419" },
123 { "es-Latn-CL", "es-Latn-419" },
124 { "es-Latn-CO", "es-Latn-419" },
125 { "es-Latn-CR", "es-Latn-419" },
126 { "es-Latn-CU", "es-Latn-419" },
127 { "es-Latn-DO", "es-Latn-419" },
128 { "es-Latn-EC", "es-Latn-419" },
129 { "es-Latn-GT", "es-Latn-419" },
130 { "es-Latn-HN", "es-Latn-419" },
131 { "es-Latn-MX", "es-Latn-419" },
132 { "es-Latn-NI", "es-Latn-419" },
133 { "es-Latn-PA", "es-Latn-419" },
134 { "es-Latn-PE", "es-Latn-419" },
135 { "es-Latn-PR", "es-Latn-419" },
136 { "es-Latn-PY", "es-Latn-419" },
137 { "es-Latn-SV", "es-Latn-419" },
138 { "es-Latn-US", "es-Latn-419" },
139 { "es-Latn-UY", "es-Latn-419" },
140 { "es-Latn-VE", "es-Latn-419" },
141 { "pt-Latn-PT", "pt-Latn-PT" }
142 };
143
144 unordered_map<string, string> LocaleConfig::dialectMapV15 {
145 { "es-Latn-419", "es-Latn-419" },
146 { "es-Latn-BO", "es-Latn-419" },
147 { "es-Latn-BR", "es-Latn-419" },
148 { "es-Latn-BZ", "es-Latn-419" },
149 { "es-Latn-CL", "es-Latn-419" },
150 { "es-Latn-CO", "es-Latn-419" },
151 { "es-Latn-CR", "es-Latn-419" },
152 { "es-Latn-CU", "es-Latn-419" },
153 { "es-Latn-DO", "es-Latn-419" },
154 { "es-Latn-EC", "es-Latn-419" },
155 { "es-Latn-GT", "es-Latn-419" },
156 { "es-Latn-HN", "es-Latn-419" },
157 { "es-Latn-MX", "es-Latn-419" },
158 { "es-Latn-NI", "es-Latn-419" },
159 { "es-Latn-PA", "es-Latn-419" },
160 { "es-Latn-PE", "es-Latn-419" },
161 { "es-Latn-PR", "es-Latn-419" },
162 { "es-Latn-PY", "es-Latn-419" },
163 { "es-Latn-SV", "es-Latn-419" },
164 { "es-Latn-US", "es-Latn-419" },
165 { "es-Latn-UY", "es-Latn-419" },
166 { "es-Latn-VE", "es-Latn-419" },
167 { "pt-Latn-PT", "pt-Latn-PT" },
168 { "en-Latn-US", "en-Latn-US" }
169 };
170
171 unordered_map<string, string> LocaleConfig::localDigitMap {
172 { "ar", "arab" },
173 { "as", "beng" },
174 { "bn", "beng" },
175 { "fa", "arabext" },
176 { "mr", "deva" },
177 { "my", "mymr" },
178 { "ne", "deva" },
179 { "ur", "latn" }
180 };
181
182 std::unordered_map<std::string, std::vector<std::string>> LocaleConfig::dialectLanguages {
183 { "en-Latn", { "en-Latn-US", "en-Latn-GB" } },
184 { "pt-Latn", { "pt-Latn-PT", "pt-Latn-BR" } },
185 { "zh-Hant", { "zh-Hant-HK", "zh-Hant-TW" } },
186 };
187
188 std::unordered_map<std::string, std::string> LocaleConfig::resourceIdMap {
189 { "zh", "zh-Hans" },
190 { "zh-HK", "zh-Hant-HK" },
191 { "zh-TW", "zh-Hant" },
192 { "az", "az-Latn" },
193 { "bs", "bs-Latn" },
194 { "jv", "jv-Latn" },
195 { "uz", "uz-Latn" },
196 { "mn", "mn-Cyrl" },
197 };
198
199 static std::unordered_map<TemperatureType, std::string> TEMPERATURE_TYPE_TO_NAME {
200 { TemperatureType::CELSIUS, "celsius" },
201 { TemperatureType::FAHRENHEIT, "fahrenhe" },
202 { TemperatureType::KELVIN, "kelvin" }
203 };
204
205 static std::unordered_map<std::string, TemperatureType> NAME_TO_TEMPERATURE_TYPE {
206 { "celsius", TemperatureType::CELSIUS },
207 { "fahrenhe", TemperatureType::FAHRENHEIT },
208 { "kelvin", TemperatureType::KELVIN }
209 };
210
211 static std::unordered_set<std::string> FAHRENHEIT_USING_REGIONS {
212 "BS",
213 "BZ",
214 "KY",
215 "PW",
216 "US"
217 };
218
219 static std::unordered_map<WeekDay, std::string> WEEK_DAY_TO_NAME {
220 { WeekDay::MON, "mon" },
221 { WeekDay::TUE, "tue" },
222 { WeekDay::WED, "wed" },
223 { WeekDay::THU, "thu" },
224 { WeekDay::FRI, "fri" },
225 { WeekDay::SAT, "sat" },
226 { WeekDay::SUN, "sun" }
227 };
228
229 static std::unordered_map<std::string, WeekDay> NAME_TO_WEEK_DAY {
230 { "mon", WeekDay::MON },
231 { "tue", WeekDay::TUE },
232 { "wed", WeekDay::WED },
233 { "thu", WeekDay::THU },
234 { "fri", WeekDay::FRI },
235 { "sat", WeekDay::SAT },
236 { "sun", WeekDay::SUN }
237 };
238
239 std::unordered_map<icu::Calendar::EDaysOfWeek, WeekDay> LocaleConfigExt::eDaysOfWeekToWeekDay {
240 { icu::Calendar::EDaysOfWeek::MONDAY, WeekDay::MON },
241 { icu::Calendar::EDaysOfWeek::TUESDAY, WeekDay::TUE },
242 { icu::Calendar::EDaysOfWeek::WEDNESDAY, WeekDay::WED },
243 { icu::Calendar::EDaysOfWeek::THURSDAY, WeekDay::THU },
244 { icu::Calendar::EDaysOfWeek::FRIDAY, WeekDay::FRI },
245 { icu::Calendar::EDaysOfWeek::SATURDAY, WeekDay::SAT },
246 { icu::Calendar::EDaysOfWeek::SUNDAY, WeekDay::SUN }
247 };
248
249 std::map<std::string, std::string> LocaleConfig::supportedDialectLocales;
250 std::map<string, string> LocaleConfig::locale2DisplayName {};
251 std::map<string, string> LocaleConfig::region2DisplayName {};
252 std::unordered_map<std::string, bool> LocaleConfig::is24HourLocaleMap {};
253 std::string LocaleConfig::currentDialectLocale = "";
254 std::string LocaleConfig::currentOverrideRegion = "";
255 std::mutex LocaleConfig::dialectLocaleMutex;
256 std::mutex LocaleConfig::region2DisplayNameMutex;
257 std::mutex LocaleConfig::locale2DisplayNameMutex;
258 std::shared_mutex LocaleConfig::is24HourLocaleMapMutex;
259
260 set<std::string> LocaleConfig::validCaTag {
261 "buddhist",
262 "chinese",
263 "coptic",
264 "dangi",
265 "ethioaa",
266 "ethiopic",
267 "gregory",
268 "hebrew",
269 "indian",
270 "islamic",
271 "islamic-umalqura",
272 "islamic-tbla",
273 "islamic-civil",
274 "islamic-rgsa",
275 "iso8601",
276 "japanese",
277 "persian",
278 "roc",
279 "islamicc",
280 };
281 set<std::string> LocaleConfig::validCoTag {
282 "big5han",
283 "compat",
284 "dict",
285 "direct",
286 "ducet",
287 "eor",
288 "gb2312",
289 "phonebk",
290 "phonetic",
291 "pinyin",
292 "reformed",
293 "searchjl",
294 "stroke",
295 "trad",
296 "unihan",
297 "zhuyin",
298 };
299 set<std::string> LocaleConfig::validKnTag {
300 "true",
301 "false",
302 };
303 set<std::string> LocaleConfig::validKfTag {
304 "upper",
305 "lower",
306 "false",
307 };
308 set<std::string> LocaleConfig::validNuTag {
309 "adlm", "ahom", "arab", "arabext", "bali", "beng",
310 "bhks", "brah", "cakm", "cham", "deva", "diak",
311 "fullwide", "gong", "gonm", "gujr", "guru", "hanidec",
312 "hmng", "hmnp", "java", "kali", "khmr", "knda",
313 "lana", "lanatham", "laoo", "latn", "lepc", "limb",
314 "mathbold", "mathdbl", "mathmono", "mathsanb", "mathsans", "mlym",
315 "modi", "mong", "mroo", "mtei", "mymr", "mymrshan",
316 "mymrtlng", "newa", "nkoo", "olck", "orya", "osma",
317 "rohg", "saur", "segment", "shrd", "sind", "sinh",
318 "sora", "sund", "takr", "talu", "tamldec", "telu",
319 "thai", "tibt", "tirh", "vaii", "wara", "wcho",
320 };
321 set<std::string> LocaleConfig::validHcTag {
322 "h12",
323 "h23",
324 "h11",
325 "h24",
326 };
327
328 static unordered_map<string, string> g_languageMap = {
329 { "zh-Hans", "zh-Hans" },
330 { "zh-Hant-HK", "zh-Hant-HK" },
331 { "zh-Hant", "zh-Hant" },
332 { "my-Qaag", "my-Qaag" },
333 { "es-Latn-419", "es-419" },
334 { "es-Latn-US", "es-419" },
335 { "az-Latn", "az-Latn" },
336 { "bs-Latn", "bs-Latn" },
337 { "en-Latn-US", "en" },
338 { "en-Qaag", "en-Qaag" },
339 { "uz-Latn", "uz-Latn" },
340 { "sr-Latn", "sr-Latn" },
341 { "jv-Latn", "jv-Latn" },
342 { "pt-Latn-BR", "pt-BR" },
343 { "pa-Guru", "pa-Guru" },
344 { "mai-Deva", "mai-Deva" }
345 };
346
347 static const std::unordered_map<std::string, std::unordered_set<std::string>> LANGUAGE_TO_COLLATION_VALUES {
348 { "zh-Hant", { "zhuyin", "pinyin", "stroke" } },
349 { "en-Latn-US", { "upper", "lower" } }
350 };
351
352 static const std::unordered_map<std::string, std::string> LANGUAGE_TO_COLLATION_KEY {
353 { "zh-Hant", "collation" },
354 { "en-Latn-US", "colCaseFirst" }
355 };
356
357 static const std::unordered_map<std::string, std::string> LANGUAGE_TO_EXT_PARAM_KEY {
358 { "zh-Hant", "co" },
359 { "en-Latn-US", "kf" }
360 };
361
362 static const std::unordered_map<std::string, std::string> LANGUAGE_TO_DEFAULT_COLLATION_VALUE {
363 { "zh-Hant", "stroke" },
364 { "en-Latn-US", "lower" }
365 };
366
367 static const std::unordered_map<std::string, std::string> LANGUAGE_TO_NUMBERING_SYSTEM {
368 { "ar", "arab" },
369 { "as", "beng" },
370 { "bn", "beng" },
371 { "fa", "arabext" },
372 { "mr", "deva" },
373 { "my", "mymr" },
374 { "ne", "deva" },
375 { "ur", "arabext" }
376 };
377
378 static const std::unordered_map<std::string, std::string> NUMBERING_SYSTEM_NAME_TO_DESCRIPTION {
379 { "arab", "٠١٢٣٤٥٦٧٨٩" },
380 { "beng", "০১২৩৪৫৬৭৮৯" },
381 { "arabext", "۰۱۲۳۴۵۶۷۸۹" },
382 { "deva", "०१२३४५६७८९" },
383 { "mymr", "၀၁၂၃၄၅၆၇၈၉" },
384 { "latn", "0123456789" }
385 };
386
387 static const std::unordered_map<std::string, std::pair<std::string, std::string>> CODE_TO_NUMBER_PATTERN {
388 { "002c002e", { ",", "." } },
389 { "0000002e", { "", "." } },
390 { "002e002c", { ".", "," } },
391 { "0000002c", { "", "," } }
392 };
393
394 static const std::unordered_map<UMeasurementSystem, std::string> UMEASUREMENT_SYSTEM_TO_VALUE {
395 { UMeasurementSystem::UMS_UK, "uksystem"},
396 { UMeasurementSystem::UMS_SI, "metric"},
397 { UMeasurementSystem::UMS_US, "ussystem"}
398 };
399
Adjust(const string & origin)400 string Adjust(const string &origin)
401 {
402 auto iter = g_languageMap.find(origin);
403 if (iter != g_languageMap.end()) {
404 return iter->second;
405 }
406 for (iter = g_languageMap.begin(); iter != g_languageMap.end(); ++iter) {
407 string key = iter->first;
408 if (!origin.compare(0, key.length(), key)) {
409 return iter->second;
410 }
411 }
412 return origin;
413 }
414
GetDisplayLanguageInner(const string & language,const string & displayLocaleTag,bool sentenceCase)415 string GetDisplayLanguageInner(const string &language, const string &displayLocaleTag, bool sentenceCase)
416 {
417 icu::UnicodeString unistr;
418 // 0 is the start position of language, 2 is the length of zh and fa
419 if (!language.compare(0, 2, "zh") || !language.compare(0, 2, "fa") || !language.compare(0, 2, "ro")) {
420 UErrorCode status = U_ZERO_ERROR;
421 icu::Locale displayLocale = icu::Locale::forLanguageTag(displayLocaleTag.c_str(), status);
422 if (U_FAILURE(status)) {
423 return "";
424 }
425 icu::Locale tempLocale = icu::Locale::forLanguageTag(language.c_str(), status);
426 if (U_FAILURE(status)) {
427 return "";
428 }
429 icu::LocaleDisplayNames *dspNames = icu::LocaleDisplayNames::createInstance(displayLocale,
430 UDialectHandling::ULDN_DIALECT_NAMES);
431 if (dspNames != nullptr) {
432 dspNames->localeDisplayName(tempLocale, unistr);
433 delete dspNames;
434 }
435 } else {
436 UErrorCode status = U_ZERO_ERROR;
437 icu::Locale displayLoc = icu::Locale::forLanguageTag(displayLocaleTag, status);
438 if (U_FAILURE(status)) {
439 return "";
440 }
441 icu::Locale locale = icu::Locale::forLanguageTag(language, status);
442 if (U_FAILURE(status)) {
443 return "";
444 }
445 locale.getDisplayName(displayLoc, unistr);
446 }
447 if (sentenceCase) {
448 UChar32 ch = ucase_toupper(unistr.char32At(0));
449 unistr.replace(0, 1, ch);
450 }
451 string out;
452 unistr.toUTF8String(out);
453 return out;
454 }
455
456 bool LocaleConfig::listsInitialized = LocaleConfig::InitializeLists();
457
GetEffectiveLanguage()458 std::string LocaleConfig::GetEffectiveLanguage()
459 {
460 std::string systemLocale = GetSystemLocale();
461 std::string systemLanguage = GetSystemLanguage();
462 return ComputeEffectiveLanguage(systemLocale, systemLanguage);
463 }
464
GetEffectiveLocale()465 std::string LocaleConfig::GetEffectiveLocale()
466 {
467 std::string systemLocale = ReadSystemParameter(LOCALE_KEY.c_str(), CONFIG_LEN);
468 if (!systemLocale.empty()) {
469 return systemLocale;
470 }
471 systemLocale = ReadSystemParameter(DEFAULT_LOCALE_KEY, CONFIG_LEN);
472 if (systemLocale.empty()) {
473 HILOG_ERROR_I18N("LocaleConfig::GetEffectiveLocale: Read default system locale failed.");
474 return "zh-Hans-CN";
475 }
476 return systemLocale;
477 }
478
GetSystemLanguage()479 string LocaleConfig::GetSystemLanguage()
480 {
481 std::string systemLanguage = ReadSystemParameter(LANGUAGE_KEY.c_str(), CONFIG_LEN);
482 if (!systemLanguage.empty()) {
483 return systemLanguage;
484 }
485 systemLanguage = ReadSystemParameter(DEFAULT_LANGUAGE_KEY, CONFIG_LEN);
486 if (systemLanguage.empty()) {
487 HILOG_ERROR_I18N("LocaleConfig::GetSystemLanguage: Read default system language failed.");
488 return "zh-Hans";
489 }
490 return systemLanguage;
491 }
492
GetSystemRegion()493 string LocaleConfig::GetSystemRegion()
494 {
495 std::string systemRegion = GetCountry(LOCALE_KEY);
496 if (systemRegion.empty()) {
497 systemRegion = GetCountry(DEFAULT_LOCALE_KEY);
498 }
499 if (systemRegion.empty()) {
500 HILOG_ERROR_I18N("LocaleConfig::GetSystemRegion: system region is empty.");
501 return "CN";
502 }
503 return systemRegion;
504 }
505
GetCountry(const string & parameter)506 string LocaleConfig::GetCountry(const string& parameter)
507 {
508 std::string systemRegion = ReadSystemParameter(parameter.c_str(), CONFIG_LEN);
509 if (systemRegion.empty()) {
510 HILOG_ERROR_I18N("LocaleConfig::GetCountry: ReadSystemParameter %{public}s failed.", parameter.c_str());
511 return systemRegion;
512 }
513 UErrorCode status = U_ZERO_ERROR;
514 icu::Locale origin = icu::Locale::forLanguageTag(systemRegion, status);
515 if (U_FAILURE(status)) {
516 HILOG_ERROR_I18N("LocaleConfig::GetCountry: Create icu::Locale failed.");
517 return "";
518 }
519 const char* country = origin.getCountry();
520 if (country == nullptr) {
521 HILOG_ERROR_I18N("LocaleConfig::GetCountry: Get country from icu::Locale failed.");
522 return "";
523 }
524 return country;
525 }
526
GetSystemLocale()527 string LocaleConfig::GetSystemLocale()
528 {
529 std::string systemLocale = GetEffectiveLocale();
530 std::vector<std::pair<size_t, std::string>> positions = GetExtParamPositions(systemLocale);
531 if (positions[0].first != std::string::npos) {
532 systemLocale = systemLocale.substr(0, positions[0].first);
533 }
534 return systemLocale;
535 }
536
GetSystemTimezone()537 std::string LocaleConfig::GetSystemTimezone()
538 {
539 std::string systemTimezone = ReadSystemParameter(TIMEZONE_KEY.c_str(), CONFIG_LEN);
540 if (systemTimezone.empty()) {
541 HILOG_ERROR_I18N("LocaleConfig::GetSystemTimezone: Read system time zone failed.");
542 return DEFAULT_TIMEZONE;
543 }
544 return systemTimezone;
545 }
546
IsValidLanguage(const string & language)547 bool LocaleConfig::IsValidLanguage(const string &language)
548 {
549 string::size_type size = language.size();
550 if ((size != LANGUAGE_LEN) && (size != LANGUAGE_LEN + 1)) {
551 return false;
552 }
553 for (size_t i = 0; i < size; ++i) {
554 if ((language[i] > 'z') || (language[i] < 'a')) {
555 return false;
556 }
557 }
558 return true;
559 }
560
IsValidRegion(const string & region)561 bool LocaleConfig::IsValidRegion(const string ®ion)
562 {
563 string::size_type size = region.size();
564 if (size != LocaleInfo::REGION_LEN) {
565 return false;
566 }
567 for (size_t i = 0; i < LocaleInfo::REGION_LEN; ++i) {
568 if ((region[i] > 'Z') || (region[i] < 'A')) {
569 return false;
570 }
571 }
572 return true;
573 }
574
IsValidTag(const string & tag)575 bool LocaleConfig::IsValidTag(const string &tag)
576 {
577 if (!tag.size()) {
578 return false;
579 }
580 vector<string> splits;
581 Split(tag, "-", splits);
582 if (!IsValidLanguage(splits[0])) {
583 return false;
584 }
585 return true;
586 }
587
Split(const string & src,const string & sep,vector<string> & dest)588 void LocaleConfig::Split(const string &src, const string &sep, vector<string> &dest)
589 {
590 string::size_type begin = 0;
591 string::size_type end = src.find(sep);
592 while (end != string::npos) {
593 dest.push_back(src.substr(begin, end - begin));
594 begin = end + sep.size();
595 end = src.find(sep, begin);
596 }
597 if (begin != src.size()) {
598 dest.push_back(src.substr(begin));
599 }
600 }
601
Split(const string & src,const string & sep,std::unordered_set<string> & dest)602 void LocaleConfig::Split(const string &src, const string &sep, std::unordered_set<string> &dest)
603 {
604 string::size_type begin = 0;
605 string::size_type end = src.find(sep);
606 while (end != string::npos) {
607 dest.insert(src.substr(begin, end - begin));
608 begin = end + sep.size();
609 end = src.find(sep, begin);
610 }
611 if (begin != src.size()) {
612 dest.insert(src.substr(begin));
613 }
614 }
615
616 // language in white languages should have script.
GetSystemLanguages()617 std::unordered_set<std::string> LocaleConfig::GetSystemLanguages()
618 {
619 std::unordered_set<std::string> result(whiteLanguages);
620 std::unordered_set<string> blockedLanguages = GetBlockedLanguages();
621 Expunge(result, blockedLanguages);
622 return result;
623 }
624
GetSupportedLocales()625 const unordered_set<string>& LocaleConfig::GetSupportedLocales()
626 {
627 return supportedLocales;
628 }
629
GetSupportedLocalesV15()630 const unordered_set<string>& LocaleConfig::GetSupportedLocalesV15()
631 {
632 return supportedLocalesV15;
633 }
634
GetSupportedRegions()635 const unordered_set<string>& LocaleConfig::GetSupportedRegions()
636 {
637 return supportedRegions;
638 }
639
GetSystemCountries(const std::string & language)640 std::unordered_set<std::string> LocaleConfig::GetSystemCountries(const std::string& language)
641 {
642 std::unordered_set<std::string> result(supportedRegions);
643 std::unordered_set<std::string> blockedRegion = LocaleConfig::GetBlockedRegions(language);
644 Expunge(result, blockedRegion);
645 return result;
646 }
647
IsSuggested(const string & language)648 bool LocaleConfig::IsSuggested(const string &language)
649 {
650 unordered_set<string> relatedLocales;
651 vector<string> simCountries;
652 GetCountriesFromSim(simCountries);
653 GetRelatedLocales(relatedLocales, simCountries);
654 for (auto iter = relatedLocales.begin(); iter != relatedLocales.end();) {
655 if (extendWhiteLanguageList.find(*iter) == extendWhiteLanguageList.end()) {
656 iter = relatedLocales.erase(iter);
657 } else {
658 ++iter;
659 }
660 }
661 string mainLanguage = GetMainLanguage(language, dialectMap);
662 return relatedLocales.find(mainLanguage) != relatedLocales.end();
663 }
664
IsSuggested(const std::string & language,const std::string & region)665 bool LocaleConfig::IsSuggested(const std::string &language, const std::string ®ion)
666 {
667 unordered_set<string> relatedLocales;
668 vector<string> countries { region };
669 GetRelatedLocales(relatedLocales, countries);
670 for (auto iter = relatedLocales.begin(); iter != relatedLocales.end();) {
671 if (extendWhiteLanguageList.find(*iter) == extendWhiteLanguageList.end()) {
672 iter = relatedLocales.erase(iter);
673 } else {
674 ++iter;
675 }
676 }
677 string mainLanguage = GetMainLanguage(language, dialectMap);
678 return relatedLocales.find(mainLanguage) != relatedLocales.end();
679 }
680
IsSuggestedV15(const string & language)681 bool LocaleConfig::IsSuggestedV15(const string &language)
682 {
683 unordered_set<string> relatedLocales;
684 vector<string> simCountries;
685 GetCountriesFromSim(simCountries);
686 GetRelatedLocalesV15(relatedLocales, simCountries);
687 auto iter = relatedLocales.begin();
688 while (iter != relatedLocales.end()) {
689 if (extendWhiteLanguageListV15.find(*iter) == extendWhiteLanguageListV15.end()) {
690 iter = relatedLocales.erase(iter);
691 } else {
692 ++iter;
693 }
694 }
695 string mainLanguage = GetMainLanguage(language, dialectMapV15);
696 return relatedLocales.find(mainLanguage) != relatedLocales.end();
697 }
698
IsSuggestedV15(const std::string & language,const std::string & region)699 bool LocaleConfig::IsSuggestedV15(const std::string &language, const std::string ®ion)
700 {
701 unordered_set<string> relatedLocales;
702 vector<string> countries { region };
703 GetRelatedLocalesV15(relatedLocales, countries);
704 auto iter = relatedLocales.begin();
705 while (iter != relatedLocales.end()) {
706 if (extendWhiteLanguageListV15.find(*iter) == extendWhiteLanguageListV15.end()) {
707 iter = relatedLocales.erase(iter);
708 } else {
709 ++iter;
710 }
711 }
712 string mainLanguage = GetMainLanguage(language, dialectMapV15);
713 return relatedLocales.find(mainLanguage) != relatedLocales.end();
714 }
715
ExtendWhiteLanguages()716 void LocaleConfig::ExtendWhiteLanguages()
717 {
718 UErrorCode status = U_ZERO_ERROR;
719 for (auto iter = whiteLanguages.begin(); iter != whiteLanguages.end(); ++iter) {
720 extendWhiteLanguageList.insert(*iter);
721 extendWhiteLanguageListV15.insert(*iter);
722 icu::Locale locale = icu::Locale::forLanguageTag((*iter).c_str(), status);
723 locale.addLikelySubtags(status);
724 if (U_FAILURE(status)) {
725 continue;
726 }
727 const char* baseName = locale.getBaseName();
728 if (baseName != nullptr) {
729 std::string baseNameStr(baseName);
730 std::replace(baseNameStr.begin(), baseNameStr.end(), '_', '-');
731 extendWhiteLanguageList.insert(baseNameStr);
732 extendWhiteLanguageListV15.insert(baseNameStr);
733 }
734 const char* language = locale.getLanguage();
735 if (language != nullptr) {
736 std::string languageStr(language);
737 ExtendLanguageWithScript(languageStr);
738 }
739 }
740 }
741
ExtendLanguageWithScript(const std::string & languageStr)742 void LocaleConfig::ExtendLanguageWithScript(const std::string &languageStr)
743 {
744 if (languageStr.empty()) {
745 HILOG_ERROR_I18N("ExtendLanguageWithScript languageStr is empty.");
746 return;
747 }
748 string mainLanguage = GetMainLanguage(languageStr, dialectMap);
749 if (!mainLanguage.empty()) {
750 extendWhiteLanguageList.insert(mainLanguage);
751 }
752 }
753
GetRelatedLocales(unordered_set<string> & relatedLocales,vector<string> countries)754 void LocaleConfig::GetRelatedLocales(unordered_set<string> &relatedLocales, vector<string> countries)
755 {
756 // remove unsupported countries
757 const unordered_set<string> ®ions = GetSupportedRegions();
758 auto iter = countries.begin();
759 while (iter != countries.end()) {
760 if (regions.find(*iter) == regions.end()) {
761 iter = countries.erase(iter);
762 } else {
763 ++iter;
764 }
765 }
766 const unordered_set<string> &locales = GetSupportedLocales();
767 for (const string &locale : locales) {
768 bool find = false;
769 for (string &country : countries) {
770 if (locale.find(country) != string::npos) {
771 find = true;
772 break;
773 }
774 }
775 if (!find) {
776 continue;
777 }
778 string mainLanguage = GetMainLanguage(locale, dialectMap);
779 if (!mainLanguage.empty()) {
780 relatedLocales.insert(mainLanguage);
781 }
782 }
783 }
784
GetRelatedLocalesV15(unordered_set<string> & relatedLocales,vector<string> countries)785 void LocaleConfig::GetRelatedLocalesV15(unordered_set<string> &relatedLocales, vector<string> countries)
786 {
787 // remove unsupported countries
788 const unordered_set<string> ®ions = GetSupportedRegions();
789 auto iter = countries.begin();
790 while (iter != countries.end()) {
791 if (regions.find(*iter) == regions.end()) {
792 iter = countries.erase(iter);
793 } else {
794 ++iter;
795 }
796 }
797 const unordered_set<string> &locales = GetSupportedLocalesV15();
798 for (const string &locale : locales) {
799 bool find = false;
800 for (const string &country : countries) {
801 if (locale.find(country) != string::npos) {
802 find = true;
803 break;
804 }
805 }
806 if (!find) {
807 continue;
808 }
809 string mainLanguage = GetMainLanguage(locale, dialectMapV15);
810 if (!mainLanguage.empty()) {
811 relatedLocales.insert(mainLanguage);
812 }
813 }
814 }
815
GetCountriesFromSim(vector<string> & simCountries)816 void LocaleConfig::GetCountriesFromSim(vector<string> &simCountries)
817 {
818 simCountries.push_back(GetSystemRegion());
819 char value[CONFIG_LEN];
820 int code = GetParameter(SIM_COUNTRY_CODE_KEY, "", value, CONFIG_LEN);
821 if (code > 0) {
822 simCountries.push_back(value);
823 }
824 }
825
GetListFromFile(const char * path,const char * resourceName,unordered_set<string> & ret)826 void LocaleConfig::GetListFromFile(const char *path, const char *resourceName, unordered_set<string> &ret)
827 {
828 xmlKeepBlanksDefault(0);
829 if (!path) {
830 return;
831 }
832 xmlDocPtr doc = xmlParseFile(path);
833 if (!doc) {
834 return;
835 }
836 xmlNodePtr cur = xmlDocGetRootElement(doc);
837 if (!cur || xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>(resourceName))) {
838 xmlFreeDoc(doc);
839 return;
840 }
841 cur = cur->xmlChildrenNode;
842 xmlChar *content = nullptr;
843 while (cur != nullptr) {
844 content = xmlNodeGetContent(cur);
845 if (content != nullptr) {
846 ret.insert(reinterpret_cast<const char*>(content));
847 xmlFree(content);
848 cur = cur->next;
849 } else {
850 break;
851 }
852 }
853 xmlFreeDoc(doc);
854 }
855
Expunge(unordered_set<string> & src,const unordered_set<string> & another)856 void LocaleConfig::Expunge(unordered_set<string> &src, const unordered_set<string> &another)
857 {
858 for (auto iter = src.begin(); iter != src.end();) {
859 if (another.find(*iter) != another.end()) {
860 iter = src.erase(iter);
861 } else {
862 ++iter;
863 }
864 }
865 }
866
InitializeLists()867 bool LocaleConfig::InitializeLists()
868 {
869 SetHwIcuDirectory();
870 LoadRegionsLanguages();
871 GetListFromFile(SUPPORTED_LOCALES_PATH, SUPPORTED_LOCALES_NAME, supportedLocales);
872 GetListFromFile(SUPPORTED_LOCALES_OLD_PATH, SUPPORTED_LOCALES_NAME, supportedLocalesV15);
873 GetListFromFile(SUPPORT_LOCALES_PATH, SUPPORT_LOCALES_NAME, supportLocales);
874 GetListFromFile(OVERRIDE_SUPPORTED_REGIONS_PATH, OVERRIDE_SUPPORTED_REGIONS_NAME, overrideSupportedRegions);
875 GetListFromFile(DIALECT_LANGS_PATH, DIALECT_LANGS_NAME, dialectLang);
876 ExtendWhiteLanguages();
877 return true;
878 }
879
CleanupXmlResources()880 __attribute__((destructor)) void LocaleConfig::CleanupXmlResources()
881 {
882 if (listsInitialized) {
883 xmlCleanupParser();
884 }
885 }
886
LoadRegionsLanguages()887 void LocaleConfig::LoadRegionsLanguages()
888 {
889 char buf[MAX_PATH_LEN] = {0};
890 char* path = GetOneCfgFile(REGIONS_LANGUAGES_PATH, buf, MAX_PATH_LEN);
891 xmlKeepBlanksDefault(0);
892 if (!path) {
893 return;
894 }
895 xmlDocPtr doc = xmlParseFile(path);
896 if (!doc) {
897 return;
898 }
899 xmlNodePtr cur = xmlDocGetRootElement(doc);
900 if (!cur || xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>(REGIONS_LANGUAGES_NAME))) {
901 xmlFreeDoc(doc);
902 return;
903 }
904 cur = cur->xmlChildrenNode;
905 xmlChar *content = nullptr;
906 while (cur != nullptr) {
907 content = xmlNodeGetContent(cur);
908 if (content != nullptr && !xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>(SUPPORTED_REGIONS_NAME))) {
909 Split(reinterpret_cast<const char*>(content), ",", supportedRegions);
910 } else if (content != nullptr && !xmlStrcmp(cur->name,
911 reinterpret_cast<const xmlChar *>(WHITE_LANGUAGES_NAME))) {
912 Split(reinterpret_cast<const char*>(content), ",", whiteLanguages);
913 }
914 if (content != nullptr) {
915 xmlFree(content);
916 }
917 cur = cur->next;
918 }
919 xmlFreeDoc(doc);
920 }
921
GetMainLanguage(const string & language,std::unordered_map<std::string,std::string> selfDialectMap)922 string LocaleConfig::GetMainLanguage(const string &language,
923 std::unordered_map<std::string, std::string> selfDialectMap)
924 {
925 UErrorCode status = U_ZERO_ERROR;
926 icu::Locale origin = icu::Locale::forLanguageTag(language, status);
927 if (U_FAILURE(status)) {
928 return "";
929 }
930 origin.addLikelySubtags(status);
931 if (U_FAILURE(status)) {
932 return "";
933 }
934 icu::LocaleBuilder builder = icu::LocaleBuilder().setLanguage(origin.getLanguage()).
935 setScript(origin.getScript()).setRegion(origin.getCountry());
936 icu::Locale temp = builder.setExtension('u', "").build(status);
937 if (U_FAILURE(status)) {
938 return "";
939 }
940 string fullLanguage = temp.toLanguageTag<string>(status);
941 if (U_FAILURE(status)) {
942 return "";
943 }
944 if (selfDialectMap.find(fullLanguage) != selfDialectMap.end()) {
945 return selfDialectMap[fullLanguage];
946 }
947 builder.setRegion("");
948 temp = builder.build(status);
949 if (U_FAILURE(status)) {
950 return "";
951 }
952 fullLanguage = temp.toLanguageTag<string>(status);
953 if (U_FAILURE(status)) {
954 return "";
955 }
956 return fullLanguage;
957 }
958
GetDisplayLanguage(const string & language,const string & displayLocale,bool sentenceCase)959 string LocaleConfig::GetDisplayLanguage(const string &language, const string &displayLocale, bool sentenceCase)
960 {
961 std::string result = GetPseudoDisplayLanguage(language);
962 if (!result.empty()) {
963 return result;
964 }
965 string adjust = Adjust(language);
966 if (adjust == language) {
967 UErrorCode status = U_ZERO_ERROR;
968 icu::Locale displayLoc = icu::Locale::forLanguageTag(displayLocale, status);
969 if (U_FAILURE(status)) {
970 return PseudoLocalizationProcessor("");
971 }
972 icu::Locale locale = icu::Locale::forLanguageTag(language, status);
973 if (U_FAILURE(status)) {
974 return PseudoLocalizationProcessor("");
975 }
976 icu::UnicodeString unistr;
977 std::string lang(locale.getLanguage());
978 if (dialectLang.find(lang) != dialectLang.end()) {
979 result = GetDisplayLanguageWithDialect(language, displayLocale);
980 }
981 }
982 if (result.empty()) {
983 result = GetDisplayLanguageInner(adjust, displayLocale, sentenceCase);
984 }
985 TabooUtils* tabooUtils = TabooUtils::GetInstance();
986 if (tabooUtils != nullptr) {
987 result = tabooUtils->ReplaceLanguageName(adjust, displayLocale, result);
988 } else {
989 HILOG_ERROR_I18N("LocaleConfig::GetDisplayLanguage: tabooUtils is nullptr.");
990 }
991 if (sentenceCase && !result.empty()) {
992 char ch = static_cast<char>(toupper(result[0]));
993 return PseudoLocalizationProcessor(result.replace(0, 1, 1, ch));
994 }
995 return PseudoLocalizationProcessor(result);
996 }
997
GetPseudoDisplayLanguage(const std::string & language)998 std::string LocaleConfig::GetPseudoDisplayLanguage(const std::string &language)
999 {
1000 if (language.compare("en-XA") == 0) {
1001 return "[Pseudo locale]";
1002 }
1003 if (language.compare("ar-XB") == 0) {
1004 return "[Bidirection test locale]";
1005 }
1006 return "";
1007 }
1008
ComputeLocale(const std::string & displayLocale)1009 std::string LocaleConfig::ComputeLocale(const std::string &displayLocale)
1010 {
1011 if (supportedDialectLocales.size() == 0) {
1012 xmlKeepBlanksDefault(0);
1013 xmlDocPtr doc = xmlParseFile(SUPPORT_LOCALES_PATH);
1014 if (!doc) {
1015 return "";
1016 }
1017 xmlNodePtr cur = xmlDocGetRootElement(doc);
1018 if (!cur || xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>(supportLocalesTag))) {
1019 xmlFreeDoc(doc);
1020 HILOG_ERROR_I18N("can not parse language supported locale file");
1021 return "";
1022 }
1023 cur = cur->xmlChildrenNode;
1024 while (cur != nullptr) {
1025 xmlChar *content = xmlNodeGetContent(cur);
1026 if (content == nullptr) {
1027 HILOG_ERROR_I18N("get xml node content failed");
1028 break;
1029 }
1030 std::map<std::string, std::string> localeInfoConfigs = {};
1031 LocaleInfo localeinfo(reinterpret_cast<const char*>(content), localeInfoConfigs);
1032 std::string maximizeLocale = localeinfo.Maximize();
1033 const char* key = maximizeLocale.c_str();
1034 const char* value = reinterpret_cast<const char*>(content);
1035 SetSupportedDialectLocales(key, value);
1036 xmlFree(content);
1037 cur = cur->next;
1038 }
1039 xmlFreeDoc(doc);
1040 }
1041 std::map<std::string, std::string> configs = {};
1042 LocaleInfo localeinfo(displayLocale, configs);
1043 std::string maximizeLocale = localeinfo.Maximize();
1044 if (supportedDialectLocales.find(maximizeLocale) != supportedDialectLocales.end()) {
1045 return supportedDialectLocales.at(maximizeLocale);
1046 }
1047 return "";
1048 }
1049
SetSupportedDialectLocales(const char * key,const char * value)1050 void LocaleConfig::SetSupportedDialectLocales(const char* key, const char* value)
1051 {
1052 std::lock_guard<std::mutex> dialectLocaleLock(dialectLocaleMutex);
1053 supportedDialectLocales.insert(
1054 std::make_pair<std::string, std::string>(key, value));
1055 }
1056
ReadLangData(const char * langDataPath)1057 void LocaleConfig::ReadLangData(const char *langDataPath)
1058 {
1059 xmlKeepBlanksDefault(0);
1060 if (langDataPath == nullptr) {
1061 return;
1062 }
1063 xmlDocPtr doc = xmlParseFile(langDataPath);
1064 if (!doc) {
1065 HILOG_ERROR_I18N("can not open language data file");
1066 return;
1067 }
1068 xmlNodePtr cur = xmlDocGetRootElement(doc);
1069 if (!cur || xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>(rootTag))) {
1070 xmlFreeDoc(doc);
1071 HILOG_ERROR_I18N("parse language data file failed");
1072 return;
1073 }
1074 cur = cur->xmlChildrenNode;
1075 while (cur != nullptr && !xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>(secondRootTag))) {
1076 xmlChar *langContents[ELEMENT_NUM] = { 0 }; // 2 represent langid, displayname;
1077 xmlNodePtr langValue = cur->xmlChildrenNode;
1078 bool xmlNodeNull = false;
1079 for (size_t i = 0; i < ELEMENT_NUM && langValue != nullptr; i++) {
1080 langContents[i] = xmlNodeGetContent(langValue);
1081 langValue = langValue->next;
1082 if (langContents[i] == nullptr) {
1083 xmlNodeNull = true;
1084 }
1085 }
1086 if (!xmlNodeNull) {
1087 // 0 represents langid index, 1 represents displayname index
1088 const char* key = reinterpret_cast<const char *>(langContents[0]);
1089 const char* value = reinterpret_cast<const char *>(langContents[1]);
1090 SetLocale2DisplayName(key, value);
1091 }
1092 for (size_t i = 0; i < ELEMENT_NUM; i++) {
1093 if (langContents[i] != nullptr) {
1094 xmlFree(langContents[i]);
1095 }
1096 }
1097 cur = cur->next;
1098 }
1099 xmlFreeDoc(doc);
1100 }
1101
SetRegion2DisplayName(const char * key,const char * value)1102 void LocaleConfig::SetRegion2DisplayName(const char* key, const char* value)
1103 {
1104 std::lock_guard<std::mutex> regionDisplayLock(region2DisplayNameMutex);
1105 region2DisplayName.insert(
1106 std::make_pair<std::string, std::string>(key, value));
1107 }
1108
SetLocale2DisplayName(const char * key,const char * value)1109 void LocaleConfig::SetLocale2DisplayName(const char* key, const char* value)
1110 {
1111 std::lock_guard<std::mutex> localeDisplayLock(locale2DisplayNameMutex);
1112 locale2DisplayName.insert(
1113 std::make_pair<std::string, std::string>(key, value));
1114 }
1115
ReadRegionData(const char * regionDataPath)1116 void LocaleConfig::ReadRegionData(const char *regionDataPath)
1117 {
1118 xmlKeepBlanksDefault(0);
1119 if (regionDataPath == nullptr) {
1120 return;
1121 }
1122 xmlDocPtr doc = xmlParseFile(regionDataPath);
1123 if (!doc) {
1124 HILOG_ERROR_I18N("can not open region data file");
1125 return;
1126 }
1127 xmlNodePtr cur = xmlDocGetRootElement(doc);
1128 if (!cur || xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>(rootRegion))) {
1129 xmlFreeDoc(doc);
1130 HILOG_ERROR_I18N("parse region data file failed");
1131 return;
1132 }
1133 cur = cur->xmlChildrenNode;
1134 while (cur != nullptr && !xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>(secondRootRegion))) {
1135 xmlChar *regionContents[ELEMENT_NUM] = { 0 };
1136 xmlNodePtr regionValue = cur->xmlChildrenNode;
1137 bool xmlNodeNull = false;
1138 for (size_t i = 0; i < ELEMENT_NUM && regionValue != nullptr; i++) {
1139 regionContents[i] = xmlNodeGetContent(regionValue);
1140 regionValue = regionValue->next;
1141 if (regionContents[i] == nullptr) {
1142 xmlNodeNull = true;
1143 }
1144 }
1145 if (!xmlNodeNull) {
1146 // 0 represents langid index, 1 represents displayname index
1147 const char* regionKey = reinterpret_cast<const char *>(regionContents[0]);
1148 const char* regionVal = reinterpret_cast<const char *>(regionContents[1]);
1149 SetRegion2DisplayName(regionKey, regionVal);
1150 }
1151 for (size_t i = 0; i < ELEMENT_NUM; i++) {
1152 if (regionContents[i] != nullptr) {
1153 xmlFree(regionContents[i]);
1154 }
1155 }
1156 cur = cur->next;
1157 }
1158 xmlFreeDoc(doc);
1159 }
1160
GetDisplayLanguageWithDialect(const std::string & localeStr,const std::string & displayLocale)1161 string LocaleConfig::GetDisplayLanguageWithDialect(const std::string &localeStr, const std::string &displayLocale)
1162 {
1163 std::string finalLocale = ComputeLocale(displayLocale);
1164 if (finalLocale.empty()) {
1165 return "";
1166 }
1167 if (finalLocale.compare(currentDialectLocale) != 0) {
1168 std::string xmlPath = LANG_PATH + finalLocale + ".xml";
1169 locale2DisplayName.clear();
1170 ReadLangData(xmlPath.c_str());
1171 currentDialectLocale = finalLocale;
1172 }
1173 if (locale2DisplayName.find(localeStr) != locale2DisplayName.end()) {
1174 return locale2DisplayName.at(localeStr);
1175 }
1176 std::map<std::string, std::string> configs = {};
1177 LocaleInfo locale(localeStr, configs);
1178 std::string language = locale.GetLanguage();
1179 std::string scripts = locale.GetScript();
1180 std::string region = locale.GetRegion();
1181 if (scripts.length() != 0) {
1182 std::string languageAndScripts = language + "-" + scripts;
1183 if (locale2DisplayName.find(languageAndScripts) != locale2DisplayName.end()) {
1184 return locale2DisplayName.at(languageAndScripts);
1185 }
1186 }
1187 if (region.length() != 0) {
1188 std::string languageAndRegion = language + "-" + region;
1189 if (locale2DisplayName.find(languageAndRegion) != locale2DisplayName.end()) {
1190 return locale2DisplayName.at(languageAndRegion);
1191 }
1192 }
1193 if (locale2DisplayName.find(language) != locale2DisplayName.end()) {
1194 return locale2DisplayName.at(language);
1195 }
1196 return "";
1197 }
1198
GetDisplayOverrideRegion(const std::string & region,const std::string & displayLocale)1199 string LocaleConfig::GetDisplayOverrideRegion(const std::string ®ion, const std::string &displayLocale)
1200 {
1201 UErrorCode status = U_ZERO_ERROR;
1202 icu::Locale originLocale;
1203 icu::UnicodeString displayRegion;
1204 if (displayLocale.compare(currentOverrideRegion) != 0) {
1205 std::string xmlPath = REGION_PATH + displayLocale + ".xml";
1206 region2DisplayName.clear();
1207 ReadRegionData(xmlPath.c_str());
1208 currentOverrideRegion = displayLocale;
1209 }
1210 if (region2DisplayName.find(region) != region2DisplayName.end()) {
1211 return region2DisplayName.at(region);
1212 } else {
1213 icu::Locale locale = icu::Locale::forLanguageTag(displayLocale, status);
1214 if (U_FAILURE(status)) {
1215 return "";
1216 }
1217 if (IsValidRegion(region)) {
1218 icu::LocaleBuilder builder = icu::LocaleBuilder().setRegion(region);
1219 originLocale = builder.build(status);
1220 } else {
1221 originLocale = icu::Locale::forLanguageTag(region, status);
1222 }
1223 if (U_FAILURE(status)) {
1224 return "";
1225 }
1226 originLocale.getDisplayCountry(locale, displayRegion);
1227 std::string result;
1228 displayRegion.toUTF8String(result);
1229 return result;
1230 }
1231 }
1232
GetDisplayRegion(const string & region,const string & displayLocale,bool sentenceCase)1233 string LocaleConfig::GetDisplayRegion(const string ®ion, const string &displayLocale, bool sentenceCase)
1234 {
1235 UErrorCode status = U_ZERO_ERROR;
1236 icu::Locale originLocale;
1237 if (IsValidRegion(region)) {
1238 icu::LocaleBuilder builder = icu::LocaleBuilder().setRegion(region);
1239 originLocale = builder.build(status);
1240 } else {
1241 originLocale = icu::Locale::forLanguageTag(region, status);
1242 }
1243 if (U_FAILURE(status)) {
1244 return PseudoLocalizationProcessor("");
1245 }
1246 std::string country(originLocale.getCountry());
1247 if (country.empty()) {
1248 return PseudoLocalizationProcessor("");
1249 }
1250 icu::Locale locale = icu::Locale::forLanguageTag(displayLocale, status);
1251 if (U_FAILURE(status)) {
1252 return PseudoLocalizationProcessor("");
1253 }
1254 icu::UnicodeString unistr;
1255 icu::UnicodeString displayRegion;
1256 std::string result;
1257 if (overrideSupportedRegions.find(displayLocale) != overrideSupportedRegions.end()) {
1258 result = GetDisplayOverrideRegion(region, displayLocale);
1259 } else {
1260 originLocale.getDisplayCountry(locale, displayRegion);
1261 displayRegion.toUTF8String(result);
1262 }
1263 TabooUtils* tabooUtils = TabooUtils::GetInstance();
1264 if (tabooUtils != nullptr) {
1265 result = tabooUtils->ReplaceCountryName(region, displayLocale, result);
1266 } else {
1267 HILOG_ERROR_I18N("LocaleConfig::GetDisplayRegion: tabooUtils is nullptr.");
1268 }
1269 if (sentenceCase) {
1270 char ch = static_cast<char>(toupper(result[0]));
1271 return PseudoLocalizationProcessor(result.replace(0, 1, 1, ch));
1272 }
1273 return PseudoLocalizationProcessor(result);
1274 }
1275
IsRTL(const string & locale)1276 bool LocaleConfig::IsRTL(const string &locale)
1277 {
1278 icu::Locale curLocale(locale.c_str());
1279 return curLocale.isRightToLeft();
1280 }
1281
parseExtension(const std::string & extension,std::map<std::string,std::string> & map)1282 void parseExtension(const std::string &extension, std::map<std::string, std::string> &map)
1283 {
1284 std::string pattern = "-..-";
1285 std::regex express(pattern);
1286
1287 std::regex_token_iterator<std::string::const_iterator> begin1(extension.cbegin(), extension.cend(), express);
1288 std::regex_token_iterator<std::string::const_iterator> begin2(extension.cbegin(), extension.cend(), express, -1);
1289 begin2++;
1290 for (; begin1 != std::sregex_token_iterator() && begin2 != std::sregex_token_iterator(); begin1++, begin2++) {
1291 map.insert(std::pair<std::string, std::string>(begin1->str(), begin2->str()));
1292 }
1293 }
1294
setExtension(std::string & extension,const std::string & tag,const std::set<string> & validValue,const std::map<std::string,std::string> & extensionMap,const std::map<std::string,std::string> & defaultExtensionMap)1295 void setExtension(std::string &extension, const std::string &tag, const std::set<string> &validValue,
1296 const std::map<std::string, std::string> &extensionMap,
1297 const std::map<std::string, std::string> &defaultExtensionMap)
1298 {
1299 std::string value;
1300 auto it = extensionMap.find(tag);
1301 if (it != extensionMap.end()) {
1302 value = it->second;
1303 if (validValue.find(value) == validValue.end()) {
1304 return;
1305 } else {
1306 extension += tag;
1307 extension += value;
1308 }
1309 } else {
1310 it = defaultExtensionMap.find(tag);
1311 if (it != defaultExtensionMap.end()) {
1312 value = it->second;
1313 if (validValue.find(value) == validValue.end()) {
1314 return;
1315 } else {
1316 extension += tag;
1317 extension += value;
1318 }
1319 }
1320 }
1321 }
1322
setOtherExtension(std::string & extension,std::map<std::string,std::string> & extensionMap,std::map<std::string,std::string> & defaultExtensionMap)1323 void setOtherExtension(std::string &extension, std::map<std::string, std::string> &extensionMap,
1324 std::map<std::string, std::string> &defaultExtensionMap)
1325 {
1326 std::set<std::string> tags;
1327 tags.insert("-ca-");
1328 tags.insert("-co-");
1329 tags.insert("-kn-");
1330 tags.insert("-kf-");
1331 tags.insert("-nu-");
1332 tags.insert("-hc-");
1333
1334 for (auto it = tags.begin(); it != tags.end(); it++) {
1335 extensionMap.erase(*it);
1336 defaultExtensionMap.erase(*it);
1337 }
1338
1339 for (auto it = defaultExtensionMap.begin(); it != defaultExtensionMap.end(); it++) {
1340 extensionMap.insert(std::pair<std::string, std::string>(it->first, it->second));
1341 }
1342
1343 for (auto it = extensionMap.begin(); it != extensionMap.end(); it++) {
1344 extension += it->first;
1345 extension += it->second;
1346 }
1347 }
1348
GetValidLocale(const std::string & localeTag)1349 std::string LocaleConfig::GetValidLocale(const std::string &localeTag)
1350 {
1351 std::string baseLocale = "";
1352 std::string extension = "";
1353 std::size_t found = localeTag.find(STANDARD_EXT_PARAM_KEY);
1354 baseLocale = localeTag.substr(0, found);
1355 if (found != std::string::npos) {
1356 extension = localeTag.substr(found);
1357 }
1358 std::map<std::string, std::string> extensionMap;
1359 if (extension != "") {
1360 parseExtension(extension, extensionMap);
1361 }
1362
1363 std::string systemLocaleTag = GetEffectiveLocale();
1364 std::string defaultExtension = "";
1365 found = systemLocaleTag.find(STANDARD_EXT_PARAM_KEY);
1366 if (found != std::string::npos) {
1367 defaultExtension = systemLocaleTag.substr(found);
1368 }
1369 std::map<std::string, std::string> defaultExtensionMap;
1370 if (defaultExtension != "") {
1371 parseExtension(defaultExtension, defaultExtensionMap);
1372 }
1373
1374 std::string ext = "";
1375 setExtension(ext, "-ca-", validCaTag, extensionMap, defaultExtensionMap);
1376 setExtension(ext, "-co-", validCoTag, extensionMap, defaultExtensionMap);
1377 setExtension(ext, "-kn-", validKnTag, extensionMap, defaultExtensionMap);
1378 setExtension(ext, "-kf-", validKfTag, extensionMap, defaultExtensionMap);
1379 setExtension(ext, "-nu-", validNuTag, extensionMap, defaultExtensionMap);
1380 setExtension(ext, "-hc-", validHcTag, extensionMap, defaultExtensionMap);
1381
1382 std::string otherExt = "";
1383 setOtherExtension(otherExt, extensionMap, defaultExtensionMap);
1384 if (ext != "" || otherExt != "") {
1385 return baseLocale + "-u" + ext + otherExt;
1386 } else {
1387 return baseLocale;
1388 }
1389 }
1390
IsEmpty24HourClock()1391 bool LocaleConfig::IsEmpty24HourClock()
1392 {
1393 std::string is24Hour = ReadSystemParameter(HOUR_KEY.c_str(), CONFIG_LEN);
1394 if (is24Hour.empty()) {
1395 HILOG_ERROR_I18N("LocaleConfig::IsEmpty24HourClock: Read system is24Hour failed.");
1396 return false;
1397 }
1398 if (is24Hour.compare("default") == 0) {
1399 return true;
1400 }
1401 return false;
1402 }
1403
Is24HourClock()1404 bool LocaleConfig::Is24HourClock()
1405 {
1406 std::string is24Hour = ReadSystemParameter(HOUR_KEY.c_str(), CONFIG_LEN);
1407 if (is24Hour.empty()) {
1408 HILOG_ERROR_I18N("LocaleConfig::Is24HourClock: Read system is24Hour failed.");
1409 return false;
1410 }
1411 if (is24Hour.compare("default") == 0) {
1412 std::string systemLocale = GetEffectiveLocale();
1413 return Is24HourLocale(systemLocale);
1414 }
1415 if (is24Hour.compare("true") == 0) {
1416 return true;
1417 }
1418 return false;
1419 }
1420
GetSystemHour()1421 std::string LocaleConfig::GetSystemHour()
1422 {
1423 std::string is24HourVal = ReadSystemParameter(HOUR_KEY.c_str(), CONFIG_LEN);
1424 HILOG_INFO_I18N("GetSystemHour: read from system param:%{public}s.", is24HourVal.c_str());
1425 bool is24Hour = Is24HourClock();
1426 return is24Hour ? "true" : "false";
1427 }
1428
Is24HourLocale(const std::string & systemLocale)1429 bool LocaleConfig::Is24HourLocale(const std::string& systemLocale)
1430 {
1431 {
1432 std::shared_lock<std::shared_mutex> lock(is24HourLocaleMapMutex);
1433 if (is24HourLocaleMap.find(systemLocale) != is24HourLocaleMap.end()) {
1434 return is24HourLocaleMap[systemLocale];
1435 }
1436 }
1437 std::unique_lock<std::shared_mutex> lock(is24HourLocaleMapMutex);
1438 if (is24HourLocaleMap.find(systemLocale) != is24HourLocaleMap.end()) {
1439 return is24HourLocaleMap[systemLocale];
1440 }
1441 UErrorCode status = U_ZERO_ERROR;
1442 icu::Locale locale = icu::Locale::forLanguageTag(icu::StringPiece(systemLocale), status);
1443 if (U_FAILURE(status)) {
1444 HILOG_ERROR_I18N("Is24HourLocale: %{public}s create locale failed", systemLocale.c_str());
1445 return false;
1446 }
1447
1448 icu::UnicodeString formatPattern;
1449 icu::DateFormat* dateFormat = icu::DateFormat::createTimeInstance(icu::DateFormat::EStyle::kLong, locale);
1450 if (dateFormat == nullptr) {
1451 HILOG_ERROR_I18N("Is24HourLocale: createTimeInstance failed");
1452 return false;
1453 }
1454 icu::SimpleDateFormat* simDateFormat = static_cast<icu::SimpleDateFormat*>(dateFormat);
1455 if (simDateFormat == nullptr) {
1456 HILOG_ERROR_I18N("Is24HourLocale: failed to convert dateFormat");
1457 return false;
1458 }
1459 simDateFormat->toPattern(formatPattern);
1460 delete dateFormat;
1461 std::string pattern;
1462 formatPattern.toUTF8String(pattern);
1463 bool result = HasDesignator(pattern, 'H');
1464 is24HourLocaleMap[systemLocale] = result;
1465 return result;
1466 }
1467
HasDesignator(const std::string & pattern,const char designator)1468 bool LocaleConfig::HasDesignator(const std::string& pattern, const char designator)
1469 {
1470 if (pattern.empty()) {
1471 HILOG_ERROR_I18N("HasDesignator: pattern is empty");
1472 return false;
1473 }
1474 bool insideQuote = false;
1475 for (const auto& c : pattern) {
1476 if (c == '\'') {
1477 insideQuote = !insideQuote;
1478 } else if (!insideQuote) {
1479 if (c == designator) {
1480 return true;
1481 }
1482 }
1483 }
1484 return false;
1485 }
1486
GetUsingLocalDigit()1487 bool LocaleConfig::GetUsingLocalDigit()
1488 {
1489 std::string locale = GetEffectiveLocale();
1490 LocaleInfo localeInfo(locale);
1491 std::string language = localeInfo.GetLanguage();
1492 if (localDigitMap.find(language) == localDigitMap.end()) {
1493 return false;
1494 }
1495 std::string localNumberSystem = localDigitMap.at(language);
1496 return localNumberSystem.compare(localeInfo.GetNumberingSystem()) == 0;
1497 }
1498
GetBlockedLanguages()1499 std::unordered_set<std::string> LocaleConfig::GetBlockedLanguages()
1500 {
1501 TabooUtils* tabooUtils = TabooUtils::GetInstance();
1502 if (tabooUtils == nullptr) {
1503 HILOG_ERROR_I18N("LocaleConfig::GetBlockedLanguages: tabooUtils is nullptr.");
1504 return {};
1505 }
1506 return tabooUtils->GetBlockedLanguages();
1507 }
1508
GetBlockedRegions(const std::string & language)1509 std::unordered_set<std::string> LocaleConfig::GetBlockedRegions(const std::string& language)
1510 {
1511 TabooUtils* tabooUtils = TabooUtils::GetInstance();
1512 if (tabooUtils == nullptr) {
1513 HILOG_ERROR_I18N("LocaleConfig::GetBlockedRegions: tabooUtils is nullptr.");
1514 return {};
1515 }
1516 return tabooUtils->GetBlockedRegions(language);
1517 }
1518
SetSystemLanguage(const std::string & languageTag,int32_t userId)1519 I18nErrorCode LocaleConfig::SetSystemLanguage(const std::string &languageTag, int32_t userId)
1520 {
1521 if (!IsValidTag(languageTag)) {
1522 HILOG_ERROR_I18N("LocaleConfig::SetSystemLanguage %{public}s is not valid language tag.",
1523 languageTag.c_str());
1524 return I18nErrorCode::INVALID_LANGUAGE_TAG;
1525 }
1526 std::string languageCode = LocaleEncode(languageTag);
1527 HILOG_INFO_I18N("LocaleConfig::SetSystemLanguage: set language %{public}s.", languageCode.c_str());
1528 // save old language, reset system language to old language if update locale failed.
1529 std::string oldLanguageTag = GetSystemLanguage();
1530 if (SetParameter(LANGUAGE_KEY.c_str(), languageTag.data()) != 0) {
1531 HILOG_ERROR_I18N("LocaleConfig::SetSystemLanguage update system language failed.");
1532 return I18nErrorCode::UPDATE_SYSTEM_LANGUAGE_FAILED;
1533 }
1534 std::string newLocaleTag = UpdateLanguageOfLocale(languageTag);
1535 if (SetSystemLocale(newLocaleTag, userId) == I18nErrorCode::SUCCESS) {
1536 #ifdef SUPPORT_MULTI_USER
1537 std::string localId = (userId != -1) ? std::to_string(userId) : "";
1538 MultiUsers::SaveLanguage(localId, languageTag);
1539 #endif
1540 return I18nErrorCode::SUCCESS;
1541 }
1542 // reset system language to old language in case that system language is inconsist with system locale's lanuage.
1543 HILOG_ERROR_I18N("LocaleConfig::SetSystemLanguage update system locale failed.");
1544 SetParameter(LANGUAGE_KEY.c_str(), oldLanguageTag.data());
1545 return I18nErrorCode::UPDATE_SYSTEM_LANGUAGE_FAILED;
1546 }
1547
SetSystemRegion(const std::string & regionTag,int32_t userId)1548 I18nErrorCode LocaleConfig::SetSystemRegion(const std::string ®ionTag, int32_t userId)
1549 {
1550 QueryUpgradeLocale();
1551 if (!IsValidRegion(regionTag)) {
1552 HILOG_ERROR_I18N("LocaleConfig::SetSystemRegion %{public}s is not valid region tag.", regionTag.c_str());
1553 return I18nErrorCode::INVALID_REGION_TAG;
1554 }
1555 std::string regionCode = LocaleEncode(regionTag);
1556 HILOG_INFO_I18N("LocaleConfig::SetSystemRegion: set region %{public}s.", regionCode.c_str());
1557 return SetSystemLocale(UpdateRegionOfLocale(regionTag), userId);
1558 }
1559
QueryUpgradeLocale()1560 void LocaleConfig::QueryUpgradeLocale()
1561 {
1562 std::string upgradeLocale = ReadSystemParameter(UPGRADE_LOCALE_KEY, CONFIG_LEN);
1563 if (!upgradeLocale.empty()) {
1564 HILOG_INFO_I18N("LocaleConfig::QueryUpgradeLocale: upgrade locale is %{public}s.", upgradeLocale.c_str());
1565 }
1566 }
1567
ComputeEffectiveLanguage(const std::string & localeTag,const std::string & language)1568 std::string LocaleConfig::ComputeEffectiveLanguage(const std::string& localeTag, const std::string& language)
1569 {
1570 if (localeTag.empty()) {
1571 HILOG_ERROR_I18N("LocaleConfig::ComputeEffectiveLanguage: locale is empty.");
1572 return localeTag;
1573 }
1574 std::string locale = localeTag;
1575 std::vector<std::pair<size_t, std::string>> positions = GetExtParamPositions(localeTag);
1576 if (positions[0].first != std::string::npos) {
1577 locale = localeTag.substr(0, positions[0].first);
1578 }
1579 size_t prefixLength = 2;
1580 if (locale.compare(0, prefixLength, "es") != 0 && locale.compare(0, prefixLength, "pt") != 0) {
1581 return locale;
1582 }
1583 std::shared_ptr<LocaleInfo> esESLocale = std::make_shared<LocaleInfo>("es-ES");
1584 std::shared_ptr<LocaleInfo> esUSLocale = std::make_shared<LocaleInfo>("es-US");
1585 std::shared_ptr<LocaleInfo> ptPTLocale = std::make_shared<LocaleInfo>("pt-PT");
1586 std::shared_ptr<LocaleInfo> ptBRLocale = std::make_shared<LocaleInfo>("pt-BR");
1587 std::vector<LocaleInfo*> candidateLocales {
1588 esESLocale.get(),
1589 esUSLocale.get(),
1590 ptPTLocale.get(),
1591 ptBRLocale.get()
1592 };
1593 std::shared_ptr<LocaleInfo> requestLocale = std::make_shared<LocaleInfo>(locale);
1594 std::string bestMatchedLocale = LocaleMatcher::GetBestMatchedLocale(requestLocale.get(), candidateLocales);
1595 if (bestMatchedLocale.empty()) {
1596 HILOG_ERROR_I18N("LocaleConfig::ComputeEffectiveLanguage: Get best matched locale failed.");
1597 return locale;
1598 }
1599 if (language.empty()) {
1600 HILOG_ERROR_I18N("LocaleConfig::ComputeEffectiveLanguage: language is empty.");
1601 return locale;
1602 }
1603 std::string systemLanguage = language;
1604 if (language.compare("es") == 0) {
1605 systemLanguage = "es-ES";
1606 }
1607 if (bestMatchedLocale.compare(systemLanguage) == 0) {
1608 return locale;
1609 }
1610 return systemLanguage;
1611 }
1612
SetSystemLocale(const std::string & localeTag,int32_t userId)1613 I18nErrorCode LocaleConfig::SetSystemLocale(const std::string &localeTag, int32_t userId)
1614 {
1615 if (!IsValidTag(localeTag)) {
1616 HILOG_ERROR_I18N("LocaleConfig::SetSystemLocale %{public}s is not a valid locale tag.", localeTag.c_str());
1617 return I18nErrorCode::INVALID_LOCALE_TAG;
1618 }
1619 std::string localeCode = LocaleEncode(localeTag);
1620 HILOG_INFO_I18N("LocaleConfig::SetSystemLocale: set locale %{public}s.", localeCode.c_str());
1621 if (SetParameter(LOCALE_KEY.c_str(), localeTag.data()) != 0) {
1622 return I18nErrorCode::UPDATE_SYSTEM_LOCALE_FAILED;
1623 }
1624 std::string systemLanguage = GetSystemLanguage();
1625 std::string effectiveLanguage = ComputeEffectiveLanguage(localeTag, systemLanguage);
1626 #ifdef SUPPORT_MULTI_USER
1627 std::string localId = (userId != -1) ? std::to_string(userId) : "";
1628 MultiUsers::SaveLocale(localId, localeTag);
1629 #endif
1630 #ifdef SUPPORT_GRAPHICS
1631 UpdateConfigurationLocaleAndLanguage(localeTag, effectiveLanguage, userId);
1632 return PublishCommonEvent(EventFwk::CommonEventSupport::COMMON_EVENT_LOCALE_CHANGED, userId);
1633 #else
1634 return I18nErrorCode::SUCCESS;
1635 #endif
1636 }
1637
IsValid24HourClockValue(const std::string & tag)1638 bool LocaleConfig::IsValid24HourClockValue(const std::string &tag)
1639 {
1640 if (tag.compare("true") == 0 || tag.compare("false") == 0 || tag.compare("default") == 0) {
1641 return true;
1642 }
1643 HILOG_ERROR_I18N("IsValid24HourClockValue invalid 24 Hour clock tag: %{public}s", tag.c_str());
1644 return false;
1645 }
1646
Set24HourClock(const std::string & option,int32_t userId)1647 I18nErrorCode LocaleConfig::Set24HourClock(const std::string &option, int32_t userId)
1648 {
1649 if (!IsValid24HourClockValue(option)) {
1650 HILOG_ERROR_I18N("LocaleConfig::Set24HourClock invalid 24 Hour clock tag: %{public}s", option.c_str());
1651 return I18nErrorCode::INVALID_24_HOUR_CLOCK_TAG;
1652 }
1653 HILOG_INFO_I18N("LocaleConfig::Set24HourClock: update 24 hour clock %{public}s", option.c_str());
1654 if (SetParameter(HOUR_KEY.c_str(), option.data()) != 0) {
1655 HILOG_ERROR_I18N("LocaleConfig::Set24HourClock update 24 hour clock failed with option=%{public}s",
1656 option.c_str());
1657 return I18nErrorCode::UPDATE_24_HOUR_CLOCK_FAILED;
1658 }
1659 #ifdef SUPPORT_MULTI_USER
1660 std::string localId;
1661 if (userId != -1) {
1662 localId = std::to_string(userId);
1663 }
1664 MultiUsers::SaveIs24Hour(localId, option);
1665 #endif
1666 #ifdef SUPPORT_GRAPHICS
1667 UpdateConfiguration24Hour(option, userId);
1668 return PublishCommonEvent(EventFwk::CommonEventSupport::COMMON_EVENT_TIME_CHANGED, userId);
1669 #else
1670 return I18nErrorCode::SUCCESS;
1671 #endif
1672 }
1673
SetUsingLocalDigit(bool flag,int32_t userId)1674 I18nErrorCode LocaleConfig::SetUsingLocalDigit(bool flag, int32_t userId)
1675 {
1676 // check whether current language support local digit.
1677 std::string localeTag = GetEffectiveLocale();
1678 std::string languageTag = localeTag.substr(0, 2); // obtain 2 length language code.
1679 auto it = localDigitMap.find(languageTag);
1680 if (it == localDigitMap.end()) {
1681 HILOG_ERROR_I18N("LocaleConfig::SetUsingLocalDigit current system doesn't support set local digit");
1682 return I18nErrorCode::UPDATE_LOCAL_DIGIT_FAILED;
1683 }
1684 std::string localDigit = flag ? it->second : "";
1685 // update system locale.
1686 return SetSystemLocale(ModifyExtParam(localeTag, NUMBER_SYSTEM_KEY, localDigit, STANDARD_EXT_PARAM_KEY), userId);
1687 }
1688
SetTemperatureType(const TemperatureType & type,int32_t userId)1689 I18nErrorCode LocaleConfig::SetTemperatureType(const TemperatureType& type, int32_t userId)
1690 {
1691 if (TEMPERATURE_TYPE_TO_NAME.find(type) == TEMPERATURE_TYPE_TO_NAME.end()) {
1692 HILOG_ERROR_I18N("LocaleConfig::SetTemperatureType: temperature type failed.");
1693 return I18nErrorCode::INVALID_TEMPERATURE_TYPE;
1694 }
1695 std::string option = TEMPERATURE_TYPE_TO_NAME[type];
1696 std::string systemLocale = MultiUsers::GetSystemLocaleFromUserId(userId);
1697 // update system locale.
1698 return SetSystemLocale(ModifyExtParam(systemLocale, TEMPERATURE_UNIT_KEY, option, STANDARD_EXT_PARAM_KEY), userId);
1699 }
1700
GetTemperatureType()1701 TemperatureType LocaleConfig::GetTemperatureType()
1702 {
1703 std::string localeTag = GetEffectiveLocale();
1704 return LocaleConfig::GetTemperatureTypeFromLocale(localeTag);
1705 }
1706
GetTemperatureTypeFromLocale(const std::string & localeTag)1707 TemperatureType LocaleConfig::GetTemperatureTypeFromLocale(const std::string& localeTag)
1708 {
1709 if (localeTag.empty()) {
1710 return TemperatureType::CELSIUS;
1711 }
1712 std::unordered_map<std::string, std::unordered_map<std::string, std::string>> extParamMap =
1713 ParseAllExtParam(localeTag);
1714 std::unordered_map<std::string, std::string> stardardExtParamMap = extParamMap[STANDARD_EXT_PARAM_KEY];
1715 std::string type;
1716 if (stardardExtParamMap.find(TEMPERATURE_UNIT_KEY) != stardardExtParamMap.end()) {
1717 type = stardardExtParamMap[TEMPERATURE_UNIT_KEY];
1718 }
1719 if (!type.empty() && NAME_TO_TEMPERATURE_TYPE.find(type) != NAME_TO_TEMPERATURE_TYPE.end()) {
1720 return NAME_TO_TEMPERATURE_TYPE[type];
1721 }
1722 std::string regionTag = GetSystemRegion();
1723 if (FAHRENHEIT_USING_REGIONS.find(regionTag) != FAHRENHEIT_USING_REGIONS.end()) {
1724 return TemperatureType::FAHRENHEIT;
1725 }
1726 return TemperatureType::CELSIUS;
1727 }
1728
GetTemperatureName(const TemperatureType & type)1729 std::string LocaleConfig::GetTemperatureName(const TemperatureType& type)
1730 {
1731 if (TEMPERATURE_TYPE_TO_NAME.find(type) == TEMPERATURE_TYPE_TO_NAME.end()) {
1732 HILOG_ERROR_I18N("LocaleConfig::GetTemperatureName: temperature type failed.");
1733 return "";
1734 }
1735 if (type == TemperatureType::FAHRENHEIT) {
1736 return "fahrenheit";
1737 }
1738 return TEMPERATURE_TYPE_TO_NAME[type];
1739 }
1740
SetFirstDayOfWeek(const WeekDay & type,int32_t userId)1741 I18nErrorCode LocaleConfig::SetFirstDayOfWeek(const WeekDay& type, int32_t userId)
1742 {
1743 if (WEEK_DAY_TO_NAME.find(type) == WEEK_DAY_TO_NAME.end()) {
1744 HILOG_ERROR_I18N("LocaleConfig::SetFirstDayOfWeek: week day failed.");
1745 return I18nErrorCode::INVALID_WEEK_DAY;
1746 }
1747 std::string option = WEEK_DAY_TO_NAME[type];
1748 std::string systemLocale = MultiUsers::GetSystemLocaleFromUserId(userId);
1749 // update system locale.
1750 return SetSystemLocale(ModifyExtParam(systemLocale, WEEK_DAY_KEY, option, STANDARD_EXT_PARAM_KEY), userId);
1751 }
1752
GetFirstDayOfWeek()1753 WeekDay LocaleConfig::GetFirstDayOfWeek()
1754 {
1755 std::string localeTag = GetEffectiveLocale();
1756 if (localeTag.empty()) {
1757 HILOG_ERROR_I18N("LocaleConfig::GetFirstDayOfWeek: get system locale failed.");
1758 return WeekDay::MON;
1759 }
1760 std::unordered_map<std::string, std::unordered_map<std::string, std::string>> extParamMap =
1761 ParseAllExtParam(localeTag);
1762 std::unordered_map<std::string, std::string> stardardExtParamMap = extParamMap[STANDARD_EXT_PARAM_KEY];
1763 std::string type;
1764 if (stardardExtParamMap.find(WEEK_DAY_KEY) != stardardExtParamMap.end()) {
1765 type = stardardExtParamMap[WEEK_DAY_KEY];
1766 }
1767 if (!type.empty() && NAME_TO_WEEK_DAY.find(type) != NAME_TO_WEEK_DAY.end()) {
1768 return NAME_TO_WEEK_DAY[type];
1769 }
1770 UErrorCode status = U_ZERO_ERROR;
1771 icu::Locale tempLocale = icu::Locale::forLanguageTag(localeTag, status);
1772 if (U_FAILURE(status)) {
1773 HILOG_ERROR_I18N("LocaleConfig::GetFirstDayOfWeek: create icu::Locale failed.");
1774 return WeekDay::MON;
1775 }
1776 icu::Calendar* calendar = icu::Calendar::createInstance(tempLocale, status);
1777 if (U_FAILURE(status)) {
1778 HILOG_ERROR_I18N("LocaleConfig::GetFirstDayOfWeek: create icu::Calendar failed.");
1779 return WeekDay::MON;
1780 }
1781 icu::Calendar::EDaysOfWeek firstDay = calendar->getFirstDayOfWeek();
1782 delete calendar;
1783 return LocaleConfigExt::GetDaysOfWeekMap()[firstDay];
1784 }
1785
GetDaysOfWeekMap()1786 std::unordered_map<icu::Calendar::EDaysOfWeek, WeekDay> LocaleConfigExt::GetDaysOfWeekMap()
1787 {
1788 return eDaysOfWeekToWeekDay;
1789 }
1790
GetSystemCollations(std::unordered_map<std::string,std::string> & systemCollations)1791 I18nErrorCode LocaleConfig::GetSystemCollations(std::unordered_map<std::string, std::string>& systemCollations)
1792 {
1793 systemCollations.clear();
1794 std::string systemLanguage = LocaleConfig::GetSystemLanguage();
1795 auto it = LANGUAGE_TO_COLLATION_VALUES.find(systemLanguage);
1796 if (it == LANGUAGE_TO_COLLATION_VALUES.end()) {
1797 return I18nErrorCode::SUCCESS;
1798 }
1799 std::string effectiveLanguage = LocaleConfig::GetEffectiveLanguage();
1800 UErrorCode status = U_ZERO_ERROR;
1801 icu::Locale locale = icu::Locale::forLanguageTag(icu::StringPiece(effectiveLanguage), status);
1802 if (U_FAILURE(status)) {
1803 HILOG_ERROR_I18N("LocaleConfig::GetSystemCollations: Create icu::Locale failed.");
1804 return I18nErrorCode::FAILED;
1805 }
1806 icu::LocaleDisplayNames* localeDisplayNames = icu::LocaleDisplayNames::createInstance(locale);
1807 if (localeDisplayNames == nullptr) {
1808 HILOG_ERROR_I18N("LocaleConfig::GetSystemCollations: Create icu::LocaleDisplayNames failed.");
1809 return I18nErrorCode::FAILED;
1810 }
1811
1812 std::unordered_set<std::string> collationValues = it->second;
1813 std::string collationKey = LANGUAGE_TO_COLLATION_KEY.at(systemLanguage);
1814 for (const auto& collationValue : collationValues) {
1815 icu::UnicodeString displayName;
1816 localeDisplayNames->keyValueDisplayName(collationKey.c_str(), collationValue.c_str(), displayName);
1817 std::string value;
1818 displayName.toUTF8String(value);
1819 systemCollations.insert(std::make_pair(collationValue, value));
1820 }
1821 delete localeDisplayNames;
1822 return I18nErrorCode::SUCCESS;
1823 }
1824
GetUsingCollation(std::string & usingCollation)1825 I18nErrorCode LocaleConfig::GetUsingCollation(std::string& usingCollation)
1826 {
1827 usingCollation.clear();
1828 std::string systemLanguage = LocaleConfig::GetSystemLanguage();
1829 auto it = LANGUAGE_TO_COLLATION_VALUES.find(systemLanguage);
1830 if (it == LANGUAGE_TO_COLLATION_VALUES.end()) {
1831 return I18nErrorCode::SUCCESS;
1832 }
1833 std::string effectiveLocale = LocaleConfig::GetEffectiveLocale();
1834 std::string key = LANGUAGE_TO_EXT_PARAM_KEY.at(systemLanguage);
1835 std::string value = LocaleConfig::QueryExtParam(effectiveLocale, key, STANDARD_EXT_PARAM_KEY);
1836 if (value.empty()) {
1837 usingCollation = LANGUAGE_TO_DEFAULT_COLLATION_VALUE.at(systemLanguage);
1838 return I18nErrorCode::SUCCESS;
1839 }
1840 std::unordered_set<std::string> collationValues = it->second;
1841 if (collationValues.find(value) == collationValues.end()) {
1842 HILOG_ERROR_I18N("LocaleConfig::GetUsingCollation: ExtParam value is invalid, key is %{public}s, "
1843 "value is %{public}s.", key.c_str(), value.c_str());
1844 return I18nErrorCode::FAILED;
1845 }
1846 usingCollation = value;
1847 return I18nErrorCode::SUCCESS;
1848 }
1849
SetSystemCollation(const std::string & identifier,int32_t userId)1850 I18nErrorCode LocaleConfig::SetSystemCollation(const std::string& identifier, int32_t userId)
1851 {
1852 std::string systemLanguage = MultiUsers::GetSystemLanguageFromUserId(userId);
1853 auto it = LANGUAGE_TO_COLLATION_VALUES.find(systemLanguage);
1854 if (it == LANGUAGE_TO_COLLATION_VALUES.end()) {
1855 HILOG_ERROR_I18N("LocaleConfig::SetSystemCollation: Invalid language.");
1856 return I18nErrorCode::INVALID_PARAM;
1857 }
1858
1859 std::unordered_set<std::string> collationValues = it->second;
1860 if (collationValues.find(identifier) == collationValues.end()) {
1861 HILOG_ERROR_I18N("LocaleConfig::SetSystemCollation: Invalid identifier %{public}s.",
1862 identifier.c_str());
1863 return I18nErrorCode::INVALID_PARAM;
1864 }
1865
1866 std::string systemLocale = MultiUsers::GetSystemLocaleFromUserId(userId);
1867 std::string key = LANGUAGE_TO_EXT_PARAM_KEY.at(systemLanguage);
1868 return SetSystemLocale(ModifyExtParam(systemLocale, key, identifier, STANDARD_EXT_PARAM_KEY), userId);
1869 }
1870
GetSystemNumberingSystems(std::unordered_map<std::string,std::string> & systemNumberingSystems)1871 I18nErrorCode LocaleConfig::GetSystemNumberingSystems(
1872 std::unordered_map<std::string, std::string>& systemNumberingSystems)
1873 {
1874 std::string systemLanguage = LocaleConfig::GetSystemLanguage();
1875 return GetSystemNumberingSystemsFromLanguage(systemLanguage, systemNumberingSystems);
1876 }
1877
GetSystemNumberingSystemsFromLanguage(const std::string & language,std::unordered_map<std::string,std::string> & systemNumberingSystems)1878 I18nErrorCode LocaleConfig::GetSystemNumberingSystemsFromLanguage(const std::string& language,
1879 std::unordered_map<std::string, std::string>& systemNumberingSystems)
1880 {
1881 systemNumberingSystems.clear();
1882 auto iter = LANGUAGE_TO_NUMBERING_SYSTEM.find(language);
1883 if (iter == LANGUAGE_TO_NUMBERING_SYSTEM.end()) {
1884 return I18nErrorCode::SUCCESS;
1885 }
1886 std::string numberingSystemName = iter->second;
1887 std::string numberingSystemDescription = NUMBERING_SYSTEM_NAME_TO_DESCRIPTION.at(numberingSystemName);
1888 systemNumberingSystems.insert(std::make_pair(numberingSystemName, numberingSystemDescription));
1889 systemNumberingSystems.insert(std::make_pair(DEFAULT_NUMBERING_SYSTEM_NAME,
1890 NUMBERING_SYSTEM_NAME_TO_DESCRIPTION.at(DEFAULT_NUMBERING_SYSTEM_NAME)));
1891 return I18nErrorCode::SUCCESS;
1892 }
1893
GetUsingNumberingSystem(std::string & usingNumberingSystem)1894 I18nErrorCode LocaleConfig::GetUsingNumberingSystem(std::string& usingNumberingSystem)
1895 {
1896 usingNumberingSystem.clear();
1897 std::unordered_map<std::string, std::string> systemNumberingSystems;
1898 I18nErrorCode errCode = LocaleConfig::GetSystemNumberingSystems(systemNumberingSystems);
1899 if (errCode == I18nErrorCode::FAILED) {
1900 HILOG_ERROR_I18N("LocaleConfig::GetUsingNumberingSystem: Get system numbering systems failed.");
1901 usingNumberingSystem = DEFAULT_NUMBERING_SYSTEM_NAME;
1902 return I18nErrorCode::FAILED;
1903 }
1904 if (systemNumberingSystems.size() == 0) {
1905 return I18nErrorCode::SUCCESS;
1906 }
1907
1908 std::string effectiveLocale = LocaleConfig::GetEffectiveLocale();
1909 UErrorCode status = U_ZERO_ERROR;
1910 icu::NumberingSystem* numberingSystem = icu::NumberingSystem::createInstance(effectiveLocale.c_str(), status);
1911 if (U_FAILURE(status) || numberingSystem == nullptr) {
1912 HILOG_ERROR_I18N("LocaleConfig::GetUsingNumberingSystem: Create icu::NumberingSystem failed.");
1913 usingNumberingSystem = DEFAULT_NUMBERING_SYSTEM_NAME;
1914 return I18nErrorCode::FAILED;
1915 }
1916 usingNumberingSystem = numberingSystem->getName();
1917 delete numberingSystem;
1918 if (usingNumberingSystem.empty() ||
1919 systemNumberingSystems.find(usingNumberingSystem) == systemNumberingSystems.end()) {
1920 usingNumberingSystem = DEFAULT_NUMBERING_SYSTEM_NAME;
1921 HILOG_ERROR_I18N("LocaleConfig::GetUsingNumberingSystem: Get name failed.");
1922 return I18nErrorCode::FAILED;
1923 }
1924 return I18nErrorCode::SUCCESS;
1925 }
1926
SetSystemNumberingSystem(const std::string & identifier,int32_t userId)1927 I18nErrorCode LocaleConfig::SetSystemNumberingSystem(const std::string& identifier, int32_t userId)
1928 {
1929 std::string language = MultiUsers::GetSystemLanguageFromUserId(userId);
1930 std::unordered_map<std::string, std::string> systemNumberingSystems;
1931 I18nErrorCode errCode = GetSystemNumberingSystemsFromLanguage(language, systemNumberingSystems);
1932 if (errCode != I18nErrorCode::SUCCESS) {
1933 HILOG_ERROR_I18N("LocaleConfig::SetSystemNumberingSystem: Get system numbering systems failed.");
1934 return I18nErrorCode::FAILED;
1935 }
1936 if (systemNumberingSystems.find(identifier) == systemNumberingSystems.end()) {
1937 HILOG_ERROR_I18N("LocaleConfig::SetSystemNumberingSystem: ExtParam value is invalid, "
1938 "value is %{public}s.", identifier.c_str());
1939 return I18nErrorCode::INVALID_PARAM;
1940 }
1941
1942 std::string localeTag = MultiUsers::GetSystemLocaleFromUserId(userId);
1943 return SetSystemLocale(ModifyExtParam(localeTag, NUMBER_SYSTEM_KEY, identifier, STANDARD_EXT_PARAM_KEY), userId);
1944 }
1945
GetNumberPatternFromLocale(const std::string & localeTag)1946 std::pair<std::string, std::string> LocaleConfig::GetNumberPatternFromLocale(const std::string& localeTag)
1947 {
1948 std::pair<std::string, std::string> numberPattern;
1949 std::string value = LocaleConfig::QueryExtParam(localeTag, NUNBER_PATTERN_KEY, CUST_EXT_PARAM_KEY);
1950 if (!value.empty()) {
1951 numberPattern = HexToNumberPattern(value);
1952 return numberPattern;
1953 }
1954
1955 UErrorCode status = U_ZERO_ERROR;
1956 icu::Locale locale = icu::Locale::forLanguageTag(localeTag.c_str(), status);
1957 if (U_FAILURE(status)) {
1958 HILOG_ERROR_I18N("LocaleConfig::GetNumberPatternFromLocale: Create icu::Locale failed.");
1959 return numberPattern;
1960 }
1961 icu::DecimalFormatSymbols* decimalFormatSymbols = new icu::DecimalFormatSymbols(locale, status);
1962 if (U_FAILURE(status) || decimalFormatSymbols == nullptr) {
1963 delete decimalFormatSymbols;
1964 HILOG_ERROR_I18N("LocaleConfig::GetNumberPatternFromLocale: Create icu::DecimalFormatSymbols failed.");
1965 return numberPattern;
1966 }
1967 icu::UnicodeString groupingSeparatorSymbol
1968 = decimalFormatSymbols->getSymbol(icu::DecimalFormatSymbols::ENumberFormatSymbol::kGroupingSeparatorSymbol);
1969 icu::UnicodeString decimalSeparatorSymbol
1970 = decimalFormatSymbols->getSymbol(icu::DecimalFormatSymbols::ENumberFormatSymbol::kDecimalSeparatorSymbol);
1971 delete decimalFormatSymbols;
1972 std::string groupingPart;
1973 groupingSeparatorSymbol.toUTF8String(groupingPart);
1974 std::string decimalPart;
1975 decimalSeparatorSymbol.toUTF8String(decimalPart);
1976 numberPattern.first = groupingPart;
1977 numberPattern.second = decimalPart;
1978 return numberPattern;
1979 }
1980
GetSystemNumberPatterns(std::unordered_map<std::string,std::string> & systemNumberPatterns)1981 I18nErrorCode LocaleConfig::GetSystemNumberPatterns(std::unordered_map<std::string, std::string>& systemNumberPatterns)
1982 {
1983 std::string effectiveLocale = LocaleConfig::GetEffectiveLocale();
1984 return GetSystemNumberPatternsFromLocale(systemNumberPatterns, effectiveLocale);
1985 }
1986
GetSystemNumberPatternsFromLocale(std::unordered_map<std::string,std::string> & systemNumberPatterns,const std::string & locale)1987 I18nErrorCode LocaleConfig::GetSystemNumberPatternsFromLocale(
1988 std::unordered_map<std::string, std::string>& systemNumberPatterns, const std::string& locale)
1989 {
1990 systemNumberPatterns.clear();
1991 std::string localeWithoutCustParam = LocaleConfig::RemoveCustExtParam(locale);
1992 for (const auto& item : CODE_TO_NUMBER_PATTERN) {
1993 std::string sample = NumberFormat::GetNumberPatternSample(localeWithoutCustParam, item.second);
1994 if (sample.empty()) {
1995 HILOG_ERROR_I18N("LocaleConfig::GetSystemNumberPatternsFromLocale: Get sample failed.");
1996 continue;
1997 }
1998 systemNumberPatterns.insert(std::make_pair(item.first, sample));
1999 }
2000
2001 std::string localeWithoutExtParam = LocaleConfig::RemoveAllExtParam(locale);
2002 std::pair<std::string, std::string> numberPattern = GetNumberPatternFromLocale(localeWithoutExtParam);
2003 std::string key = NumberPatternToHex(numberPattern.first, numberPattern.second);
2004 if (key.empty()) {
2005 HILOG_ERROR_I18N("LocaleConfig::GetSystemNumberPatternsFromLocale: Get key failed, groupingSymbol is "
2006 "%{public}s, decimalSymbol is %{public}s.", numberPattern.first.c_str(), numberPattern.second.c_str());
2007 return I18nErrorCode::FAILED;
2008 }
2009
2010 if (systemNumberPatterns.find(key) == systemNumberPatterns.end()) {
2011 std::string sample = NumberFormat::GetNumberPatternSample(localeWithoutCustParam, numberPattern);
2012 if (sample.empty()) {
2013 HILOG_ERROR_I18N("LocaleConfig::GetSystemNumberPatternsFromLocale: Get sample failed.");
2014 return I18nErrorCode::FAILED;
2015 }
2016 systemNumberPatterns.insert(std::make_pair(key, sample));
2017 }
2018 return I18nErrorCode::SUCCESS;
2019 }
2020
GetUsingNumberPattern(std::string & usingNumberPattern)2021 I18nErrorCode LocaleConfig::GetUsingNumberPattern(std::string& usingNumberPattern)
2022 {
2023 usingNumberPattern.clear();
2024 std::string effectiveLocale = LocaleConfig::GetEffectiveLocale();
2025 std::pair<std::string, std::string> numberPattern = GetNumberPatternFromLocale(effectiveLocale);
2026 std::string numberPatternHex = NumberPatternToHex(numberPattern.first, numberPattern.second);
2027 if (numberPatternHex.empty()) {
2028 HILOG_ERROR_I18N("LocaleConfig::GetUsingNumberPattern: Get numberPattern failed, groupingSymbol is %{public}s,"
2029 " decimalSymbol is %{public}s.", numberPattern.first.c_str(), numberPattern.second.c_str());
2030 return I18nErrorCode::FAILED;
2031 }
2032 usingNumberPattern = numberPatternHex;
2033 return I18nErrorCode::SUCCESS;
2034 }
2035
SetSystemNumberPattern(const std::string & pattern,int32_t userId)2036 I18nErrorCode LocaleConfig::SetSystemNumberPattern(const std::string& pattern, int32_t userId)
2037 {
2038 std::string systemLocale = MultiUsers::GetSystemLocaleFromUserId(userId);
2039 std::unordered_map<std::string, std::string> systemNumberPatterns;
2040 I18nErrorCode errCode = GetSystemNumberPatternsFromLocale(systemNumberPatterns, systemLocale);
2041 if (errCode != I18nErrorCode::SUCCESS) {
2042 HILOG_ERROR_I18N("LocaleConfig::SetSystemNumberPattern: Get system number patterns failed.");
2043 return I18nErrorCode::FAILED;
2044 }
2045
2046 if (systemNumberPatterns.find(pattern) == systemNumberPatterns.end()) {
2047 HILOG_ERROR_I18N("LocaleConfig::SetSystemNumberPattern: ExtParam value is invalid, locale is %{public}s, "
2048 "value is %{public}s.", systemLocale.c_str(), pattern.c_str());
2049 return I18nErrorCode::INVALID_PARAM;
2050 }
2051
2052 return SetSystemLocale(ModifyExtParam(systemLocale, NUNBER_PATTERN_KEY, pattern, CUST_EXT_PARAM_KEY), userId);
2053 }
2054
GetSystemMeasurements(std::unordered_map<std::string,std::string> & systemMeasurements)2055 I18nErrorCode LocaleConfig::GetSystemMeasurements(std::unordered_map<std::string, std::string>& systemMeasurements)
2056 {
2057 systemMeasurements.clear();
2058 std::string language = LocaleConfig::GetEffectiveLanguage();
2059 UErrorCode status = U_ZERO_ERROR;
2060 icu::Locale locale = icu::Locale::forLanguageTag(icu::StringPiece(language), status);
2061 if (U_FAILURE(status)) {
2062 HILOG_ERROR_I18N("LocaleConfig::GetSystemMeasurements: Create icu::Locale failed, language is %{public}s.",
2063 language.c_str());
2064 return I18nErrorCode::FAILED;
2065 }
2066 icu::LocaleDisplayNames* localeDisplayNames = icu::LocaleDisplayNames::createInstance(locale);
2067 if (localeDisplayNames == nullptr) {
2068 HILOG_ERROR_I18N("LocaleConfig::GetSystemMeasurements: Create icu::LocaleDisplayNames failed, language "
2069 "is %{public}s.", language.c_str());
2070 return I18nErrorCode::FAILED;
2071 }
2072 for (const auto& measurement : UMEASUREMENT_SYSTEM_TO_VALUE) {
2073 icu::UnicodeString displayName;
2074 localeDisplayNames->keyValueDisplayName(MEASUREMENT_KEY.c_str(), measurement.second.c_str(), displayName);
2075 std::string value;
2076 displayName.toUTF8String(value);
2077 systemMeasurements.insert(std::make_pair(measurement.second, value));
2078 }
2079 delete localeDisplayNames;
2080 return I18nErrorCode::SUCCESS;
2081 }
2082
GetUsingMeasurement(std::string & identifier)2083 I18nErrorCode LocaleConfig::GetUsingMeasurement(std::string& identifier)
2084 {
2085 identifier.clear();
2086 std::string locale = LocaleConfig::GetEffectiveLocale();
2087 identifier = LocaleConfig::GetMeasurementFromLocale(locale);
2088 if (identifier.empty()) {
2089 HILOG_ERROR_I18N("LocaleConfig::GetUsingMeasurement: Get using measurement failed.");
2090 return I18nErrorCode::FAILED;
2091 }
2092 return I18nErrorCode::SUCCESS;
2093 }
2094
GetMeasurementFromLocale(const std::string & localeTag)2095 std::string LocaleConfig::GetMeasurementFromLocale(const std::string& localeTag)
2096 {
2097 std::string extParam = LocaleConfig::QueryExtParam(localeTag, MEASUREMENT_KEY, STANDARD_EXT_PARAM_KEY);
2098 if (!extParam.empty() && LocaleConfig::IsValidMeasurement(extParam)) {
2099 return extParam;
2100 }
2101 UErrorCode status = U_ZERO_ERROR;
2102 std::string locale = LocaleConfig::RemoveAllExtParam(localeTag);
2103 UMeasurementSystem measurementSystem = ulocdata_getMeasurementSystem(locale.c_str(), &status);
2104 if (U_FAILURE(status)) {
2105 HILOG_ERROR_I18N("LocaleConfig::GetMeasurementFromLocale: Get measurementSystem failed");
2106 return "";
2107 }
2108 auto iter = UMEASUREMENT_SYSTEM_TO_VALUE.find(measurementSystem);
2109 if (iter == UMEASUREMENT_SYSTEM_TO_VALUE.end()) {
2110 HILOG_ERROR_I18N("LocaleConfig::GetMeasurementFromLocale: Invalid measurementSystem.");
2111 return "";
2112 }
2113 return iter->second;
2114 }
2115
SetSystemMeasurement(const std::string & identifier,int32_t userId)2116 I18nErrorCode LocaleConfig::SetSystemMeasurement(const std::string& identifier, int32_t userId)
2117 {
2118 if (!LocaleConfig::IsValidMeasurement(identifier)) {
2119 HILOG_ERROR_I18N("LocaleConfig::SetSystemMeasurement: Invalid identifier %{public}s.", identifier.c_str());
2120 return I18nErrorCode::INVALID_PARAM;
2121 }
2122 std::string systemLocale = MultiUsers::GetSystemLocaleFromUserId(userId);
2123 return SetSystemLocale(ModifyExtParam(systemLocale, MEASUREMENT_KEY, identifier, STANDARD_EXT_PARAM_KEY), userId);
2124 }
2125
IsValidMeasurement(const std::string & measurement)2126 bool LocaleConfig::IsValidMeasurement(const std::string& measurement)
2127 {
2128 for (const auto& item : UMEASUREMENT_SYSTEM_TO_VALUE) {
2129 if (item.second == measurement) {
2130 return true;
2131 }
2132 }
2133 return false;
2134 }
2135
GetPatternNumberFromLocale(const std::string & locale)2136 std::string LocaleConfig::GetPatternNumberFromLocale(const std::string& locale)
2137 {
2138 std::string number = LocaleConfig::QueryExtParam(locale, NUMERIC_DATE_KEY, CUST_EXT_PARAM_KEY);
2139 if (DateTimeFormat::IsValidPatternNumber(number)) {
2140 return number;
2141 }
2142 return "";
2143 }
2144
GetSystemNumericalDatePatterns(std::unordered_map<std::string,std::string> & systemNumericalDatePatterns)2145 I18nErrorCode LocaleConfig::GetSystemNumericalDatePatterns(
2146 std::unordered_map<std::string, std::string>& systemNumericalDatePatterns)
2147 {
2148 systemNumericalDatePatterns.clear();
2149 std::string systemLocale = LocaleConfig::GetSystemLocale();
2150 std::unordered_map<std::string, std::string> supportNumbers =
2151 DateTimeFormat::GetPatternsFromLocale(systemLocale);
2152 std::string effectiveLocale = LocaleConfig::GetEffectiveLocale();
2153 for (const auto& item : supportNumbers) {
2154 icu::UnicodeString pattern = item.first.c_str();
2155 std::string key;
2156 pattern.toUTF8String(key);
2157 std::string value = DateTimeFormat::GetDateSampleFromPattern(pattern, effectiveLocale);
2158 if (value.empty()) {
2159 continue;
2160 }
2161 systemNumericalDatePatterns.insert(std::make_pair(key, value));
2162 }
2163 return I18nErrorCode::SUCCESS;
2164 }
2165
GetUsingNumericalDatePattern(std::string & identifier)2166 I18nErrorCode LocaleConfig::GetUsingNumericalDatePattern(std::string& identifier)
2167 {
2168 identifier.clear();
2169 std::string effectiveLocale = LocaleConfig::GetEffectiveLocale();
2170 std::string number = LocaleConfig::QueryExtParam(effectiveLocale, NUMERIC_DATE_KEY, CUST_EXT_PARAM_KEY);
2171 if (DateTimeFormat::IsValidPatternNumber(number)) {
2172 icu::UnicodeString pattern = DateTimeFormat::GetYMDPatternFromNumber(number);
2173 pattern.toUTF8String(identifier);
2174 return I18nErrorCode::SUCCESS;
2175 }
2176
2177 std::vector<std::pair<size_t, std::string>> positions = GetExtParamPositions(effectiveLocale);
2178 std::string localeWithoutExtParam = effectiveLocale;
2179 if (positions[0].first != std::string::npos) {
2180 localeWithoutExtParam = effectiveLocale.substr(0, positions[0].first);
2181 }
2182
2183 icu::UnicodeString pattern = DateTimeFormat::GetSingleDayPatternFromLocale(localeWithoutExtParam);
2184 pattern.toUTF8String(identifier);
2185 return I18nErrorCode::SUCCESS;
2186 }
2187
SetSystemNumericalDatePattern(const std::string & identifier,int32_t userId)2188 I18nErrorCode LocaleConfig::SetSystemNumericalDatePattern(const std::string& identifier, int32_t userId)
2189 {
2190 std::string systemLocale = MultiUsers::GetSystemLocaleFromUserId(userId);
2191 std::vector<std::pair<size_t, std::string>> positions = GetExtParamPositions(systemLocale);
2192 std::string localeWithoutExtParam = systemLocale;
2193 if (positions[0].first != std::string::npos) {
2194 localeWithoutExtParam = systemLocale.substr(0, positions[0].first);
2195 }
2196 std::unordered_map<std::string, std::string> supportNumbers =
2197 DateTimeFormat::GetPatternsFromLocale(localeWithoutExtParam);
2198 auto iter = supportNumbers.find(identifier);
2199 if (iter == supportNumbers.end()) {
2200 HILOG_ERROR_I18N("LocaleConfig::SetSystemNumericalDatePattern: identifier %{public}s is invalid",
2201 identifier.c_str());
2202 return I18nErrorCode::INVALID_PARAM;
2203 }
2204 std::string extParam = iter->second;
2205 return SetSystemLocale(ModifyExtParam(systemLocale, NUMERIC_DATE_KEY, extParam, CUST_EXT_PARAM_KEY), userId);
2206 }
2207
NumberPatternToHex(const std::string & groupingSymbol,const std::string & decimalSymbol)2208 std::string LocaleConfig::NumberPatternToHex(const std::string& groupingSymbol, const std::string& decimalSymbol)
2209 {
2210 std::string hex;
2211 if (groupingSymbol.empty()) {
2212 hex += "0000";
2213 } else {
2214 std::string groupingSymbolHex = StrToHex(groupingSymbol, SYMBOL_HEX_LEN);
2215 if (groupingSymbolHex.length() != SYMBOL_HEX_LEN) {
2216 HILOG_ERROR_I18N("LocaleConfig::NumberPatternToHex: Check groupingSymbolHex failed, "
2217 "groupingSymbolHex is %{public}s.", groupingSymbolHex.c_str());
2218 return "";
2219 }
2220 hex += groupingSymbolHex;
2221 }
2222 if (decimalSymbol.empty()) {
2223 HILOG_ERROR_I18N("LocaleConfig::NumberPatternToHex: decimalSymbol is empty.");
2224 return "";
2225 }
2226 std::string decimalSymbolHex = StrToHex(decimalSymbol, SYMBOL_HEX_LEN);
2227 if (decimalSymbolHex.length() != SYMBOL_HEX_LEN) {
2228 HILOG_ERROR_I18N("LocaleConfig::NumberPatternToHex: Check decimalSymbolHex failed, "
2229 "decimalSymbolHex is %{public}s.", decimalSymbolHex.c_str());
2230 return "";
2231 }
2232 hex += decimalSymbolHex;
2233 return hex;
2234 }
2235
HexToNumberPattern(const std::string & hex)2236 std::pair<std::string, std::string> LocaleConfig::HexToNumberPattern(const std::string& hex)
2237 {
2238 std::pair<std::string, std::string> numberPattern;
2239 if (hex.length() != SYMBOL_HEX_LEN * ELEMENT_NUM) {
2240 HILOG_ERROR_I18N("LocaleConfig::HexToNumberPattern: Check hex failed, hex is %{public}s.", hex.c_str());
2241 return numberPattern;
2242 }
2243 std::string groupingSymbolHex = hex.substr(0, SYMBOL_HEX_LEN);
2244 std::string groupingSymbol;
2245 if (groupingSymbolHex.compare("0000") != 0) {
2246 groupingSymbol = HexToStr(groupingSymbolHex);
2247 if (groupingSymbol.empty()) {
2248 HILOG_ERROR_I18N("LocaleConfig::HexToNumberPattern: Get groupingSymbol failed, "
2249 "groupingSymbolHex is %{public}s.", groupingSymbolHex.c_str());
2250 return numberPattern;
2251 }
2252 }
2253
2254 std::string decimalSymbolHex = hex.substr(SYMBOL_HEX_LEN);
2255 std::string decimalSymbol = HexToStr(decimalSymbolHex);
2256 if (decimalSymbol.empty()) {
2257 HILOG_ERROR_I18N("LocaleConfig::HexToNumberPattern: Get decimalSymbol failed, "
2258 "decimalSymbolHex is %{public}s.", decimalSymbolHex.c_str());
2259 return numberPattern;
2260 }
2261 numberPattern.first = groupingSymbol;
2262 numberPattern.second = decimalSymbol;
2263 return numberPattern;
2264 }
2265
2266 #ifdef SUPPORT_GRAPHICS
UpdateConfigurationLocaleAndLanguage(const std::string & locale,const std::string & language,int32_t userId)2267 void LocaleConfig::UpdateConfigurationLocaleAndLanguage(const std::string& locale, const std::string& language,
2268 int32_t userId)
2269 {
2270 if (locale.empty() && language.empty()) {
2271 HILOG_ERROR_I18N("LocaleConfig::UpdateConfigurationLocaleAndLanguage: locale and language are empty.");
2272 return;
2273 }
2274 AppExecFwk::Configuration configuration;
2275 if (!locale.empty()) {
2276 configuration.AddItem(AAFwk::GlobalConfigurationKey::SYSTEM_LOCALE, locale);
2277 }
2278 if (!language.empty()) {
2279 configuration.AddItem(AAFwk::GlobalConfigurationKey::SYSTEM_LANGUAGE, language);
2280 }
2281 auto appMgrClient = std::make_unique<AppExecFwk::AppMgrClient>();
2282 if (appMgrClient == nullptr) {
2283 HILOG_ERROR_I18N("LocaleConfig::UpdateConfigurationLocaleAndLanguage: Get appMgrClient failed.");
2284 return;
2285 }
2286
2287 AppExecFwk::AppMgrResultCode status = appMgrClient->UpdateConfiguration(configuration, userId);
2288 if (status != AppExecFwk::AppMgrResultCode::RESULT_OK) {
2289 HILOG_ERROR_I18N("LocaleConfig::UpdateConfigurationLocaleAndLanguage: Update configuration "
2290 "userId %{public}d failed.", userId);
2291 return;
2292 }
2293 HILOG_INFO_I18N("LocaleConfig::UpdateConfigurationLocaleAndLanguage: update userId %{public}d, locale %{public}s, "
2294 "language %{public}s.", userId, locale.c_str(), language.c_str());
2295 }
2296
UpdateConfiguration24Hour(const std::string & is24Hour,int32_t userId)2297 void LocaleConfig::UpdateConfiguration24Hour(const std::string& is24Hour, int32_t userId)
2298 {
2299 AppExecFwk::Configuration configuration;
2300 configuration.AddItem(AAFwk::GlobalConfigurationKey::SYSTEM_HOUR, is24Hour);
2301 auto appMgrClient = std::make_unique<AppExecFwk::AppMgrClient>();
2302 if (appMgrClient == nullptr) {
2303 HILOG_ERROR_I18N("LocaleConfig::UpdateConfiguration24Hour: Get appMgrClient failed.");
2304 return;
2305 }
2306 AppExecFwk::AppMgrResultCode status = appMgrClient->UpdateConfiguration(configuration, userId);
2307 if (status != AppExecFwk::AppMgrResultCode::RESULT_OK) {
2308 HILOG_ERROR_I18N("LocaleConfig::UpdateConfiguration24Hour: Update configuration userId %{public}d failed.",
2309 userId);
2310 return;
2311 }
2312 HILOG_INFO_I18N("LocaleConfig::UpdateConfiguration24Hour: update userId %{public}d, is24Hour %{public}s.",
2313 userId, is24Hour.c_str());
2314 }
2315
PublishCommonEvent(const std::string & eventType,int32_t userId)2316 I18nErrorCode LocaleConfig::PublishCommonEvent(const std::string &eventType, int32_t userId)
2317 {
2318 OHOS::AAFwk::Want localeChangeWant;
2319 localeChangeWant.SetAction(eventType);
2320 OHOS::EventFwk::CommonEventData event(localeChangeWant);
2321 if (EventFwk::CommonEventSupport::COMMON_EVENT_TIME_CHANGED.compare(eventType) == 0) {
2322 event.SetData(HOUR_EVENT_DATA);
2323 }
2324 if (userId == -1) {
2325 if (!OHOS::EventFwk::CommonEventManager::PublishCommonEvent(event)) {
2326 HILOG_ERROR_I18N("LocaleConfig::PublishCommonEvent Failed to Publish event %{public}s",
2327 localeChangeWant.GetAction().c_str());
2328 return I18nErrorCode::PUBLISH_COMMON_EVENT_FAILED;
2329 }
2330 HILOG_INFO_I18N("LocaleConfig::PublishCommonEvent publish event finished.");
2331 return I18nErrorCode::SUCCESS;
2332 }
2333
2334 if (!OHOS::EventFwk::CommonEventManager::PublishCommonEventAsUser(event, userId)) {
2335 HILOG_ERROR_I18N("LocaleConfig::PublishCommonEvent Failed to Publish event %{public}s, userId %{public}d.",
2336 localeChangeWant.GetAction().c_str(), userId);
2337 return I18nErrorCode::PUBLISH_COMMON_EVENT_FAILED;
2338 }
2339 HILOG_INFO_I18N("LocaleConfig::PublishCommonEvent publish event finished, userId %{public}d.", userId);
2340 return I18nErrorCode::SUCCESS;
2341 }
2342 #endif
2343
UpdateLanguageOfLocale(const std::string & languageTag)2344 std::string LocaleConfig::UpdateLanguageOfLocale(const std::string &languageTag)
2345 {
2346 // Compute language and script part from languageTag.
2347 UErrorCode status = U_ZERO_ERROR;
2348 icu::Locale languageLocale = icu::Locale::forLanguageTag(languageTag.c_str(), status);
2349 if (U_FAILURE(status)) {
2350 HILOG_ERROR_I18N("LocaleConfig::UpdateLanguageOfLocale init icu Locale for language %{public}s failed.",
2351 languageTag.c_str());
2352 return "";
2353 }
2354 std::string langTag = languageLocale.getLanguage();
2355 std::string scriptTag = languageLocale.getScript();
2356 // Compute region and extend param part from current system locale.
2357 std::string systemLocaleTag = GetEffectiveLocale();
2358 icu::Locale systemLocale = icu::Locale::forLanguageTag(systemLocaleTag.c_str(), status);
2359 if (U_FAILURE(status)) {
2360 HILOG_ERROR_I18N("LocaleConfig::UpdateSystemLocale init icu Locale for locale %{public}s failed.",
2361 systemLocaleTag.c_str());
2362 return systemLocaleTag;
2363 }
2364 std::string regionTag = systemLocale.getCountry();
2365 std::string extendParamTag;
2366 systemLocaleTag = LocaleConfig::ModifyExtParam(systemLocaleTag, CASE_FIRST_KEY, "", STANDARD_EXT_PARAM_KEY);
2367 systemLocaleTag = LocaleConfig::ModifyExtParam(systemLocaleTag, COLLATION_KEY, "", STANDARD_EXT_PARAM_KEY);
2368 systemLocaleTag = LocaleConfig::ModifyExtParam(systemLocaleTag, NUMBER_SYSTEM_KEY, "", STANDARD_EXT_PARAM_KEY);
2369 systemLocaleTag = LocaleConfig::ModifyExtParam(systemLocaleTag, NUMERIC_DATE_KEY, "", CUST_EXT_PARAM_KEY);
2370 systemLocaleTag = LocaleConfig::ModifyExtParam(systemLocaleTag, NUNBER_PATTERN_KEY, "", CUST_EXT_PARAM_KEY);
2371 std::vector<std::pair<size_t, std::string>> positions = GetExtParamPositions(systemLocaleTag);
2372 if (positions[0].first != std::string::npos) {
2373 extendParamTag = systemLocaleTag.substr(positions[0].first);
2374 }
2375 // Combine above elements.
2376 return CreateLocale(langTag, scriptTag, regionTag, extendParamTag);
2377 }
2378
CreateLocale(const std::string & languageTag,const std::string & scriptTag,const std::string & regionTag,const std::string & extendParamTag)2379 std::string LocaleConfig::CreateLocale(const std::string &languageTag, const std::string &scriptTag,
2380 const std::string ®ionTag, const std::string &extendParamTag)
2381 {
2382 // combine language, script, region and extend param with '-'
2383 std::string localeTag = languageTag;
2384 std::string splitor = "-";
2385 if (scriptTag.length() > 0) {
2386 localeTag += splitor + scriptTag;
2387 }
2388 if (regionTag.length() > 0) {
2389 localeTag += splitor + regionTag;
2390 }
2391 if (extendParamTag.length() > 0) {
2392 localeTag += extendParamTag;
2393 }
2394 return localeTag;
2395 }
2396
UpdateRegionOfLocale(const std::string & regionTag)2397 std::string LocaleConfig::UpdateRegionOfLocale(const std::string ®ionTag)
2398 {
2399 std::string localeTag = GetEffectiveLocale();
2400 // if current system locale is null, contruct a locale from region tag.
2401 if (localeTag.empty()) {
2402 return CreateLocaleFromRegion(regionTag);
2403 }
2404 std::string extParam;
2405 std::vector<std::pair<size_t, std::string>> positions = GetExtParamPositions(localeTag);
2406 if (positions[0].first != std::string::npos) {
2407 extParam = localeTag.substr(positions[0].first);
2408 }
2409 // combine locale with origin locale's language and script with regionTag.
2410 UErrorCode status = U_ZERO_ERROR;
2411 const icu::Locale origin = icu::Locale::forLanguageTag(localeTag, status);
2412 if (U_FAILURE(status)) {
2413 HILOG_ERROR_I18N("LocaleConfig::UpdateRegionOfLocale init origin locale failed.");
2414 return localeTag;
2415 }
2416 icu::LocaleBuilder builder = icu::LocaleBuilder().setLanguage(origin.getLanguage()).
2417 setScript(origin.getScript()).setRegion(regionTag);
2418 icu::Locale temp = builder.build(status);
2419 if (U_FAILURE(status)) {
2420 HILOG_ERROR_I18N("LocaleConfig::UpdateRegionOfLocale: build locale failed.");
2421 return localeTag;
2422 }
2423 string ret = temp.toLanguageTag<string>(status);
2424 if (U_FAILURE(status)) {
2425 HILOG_ERROR_I18N("LocaleConfig::UpdateRegionOfLocale obtain new locale's tag failed.");
2426 return localeTag;
2427 }
2428 ret += extParam;
2429 ret = LocaleConfig::ModifyExtParam(ret, NUNBER_PATTERN_KEY, "", CUST_EXT_PARAM_KEY);
2430 ret = LocaleConfig::ModifyExtParam(ret, NUMERIC_DATE_KEY, "", CUST_EXT_PARAM_KEY);
2431 return ret;
2432 }
2433
CreateLocaleFromRegion(const std::string & regionTag)2434 std::string LocaleConfig::CreateLocaleFromRegion(const std::string ®ionTag)
2435 {
2436 // fill locale with icu
2437 icu::Locale locale("", regionTag.c_str());
2438 UErrorCode status = U_ZERO_ERROR;
2439 locale.addLikelySubtags(status);
2440 if (U_FAILURE(status)) {
2441 HILOG_ERROR_I18N("LocaleConfig::CreateLocaleFromRegion init new locale failed.");
2442 return "";
2443 }
2444 std::string localeTag = locale.toLanguageTag<string>(status);
2445 if (U_FAILURE(status)) {
2446 HILOG_ERROR_I18N("LocaleConfig::CreateLocaleFromRegion obtain new locale's tag failed.");
2447 return "";
2448 }
2449 return localeTag;
2450 }
2451
RemoveCustExtParam(const std::string & locale)2452 std::string LocaleConfig::RemoveCustExtParam(const std::string& locale)
2453 {
2454 std::string tempLocale = ModifyExtParam(locale, NUNBER_PATTERN_KEY, "", CUST_EXT_PARAM_KEY);
2455 return ModifyExtParam(tempLocale, NUMERIC_DATE_KEY, "", CUST_EXT_PARAM_KEY);
2456 }
2457
RemoveAllExtParam(const std::string & locale)2458 std::string LocaleConfig::RemoveAllExtParam(const std::string& locale)
2459 {
2460 std::vector<std::pair<size_t, std::string>> positions = GetExtParamPositions(locale);
2461 std::string localeWithoutExtParam = locale;
2462 if (positions[0].first != std::string::npos) {
2463 localeWithoutExtParam = locale.substr(0, positions[0].first);
2464 }
2465 return localeWithoutExtParam;
2466 }
2467
QueryExtParam(const std::string & locale,const std::string & key,const std::string & extParamKey)2468 std::string LocaleConfig::QueryExtParam(const std::string& locale, const std::string& key,
2469 const std::string& extParamKey)
2470 {
2471 if (locale.empty()) {
2472 HILOG_ERROR_I18N("LocaleConfig::QueryExtParam: locale is empty.");
2473 return "";
2474 }
2475 if (key.empty()) {
2476 HILOG_ERROR_I18N("LocaleConfig::QueryExtParam: key is empty.");
2477 return "";
2478 }
2479 std::unordered_map<std::string, std::unordered_map<std::string, std::string>> extParamMap =
2480 ParseAllExtParam(locale);
2481 std::unordered_map<std::string, std::string> paramMap = extParamMap[extParamKey];
2482 auto it = paramMap.find(key);
2483 if (it == paramMap.end()) {
2484 return "";
2485 }
2486 return it->second;
2487 }
2488
ModifyExtParam(const std::string & locale,const std::string & key,const std::string & value,const std::string & extParamKey)2489 std::string LocaleConfig::ModifyExtParam(const std::string& locale, const std::string& key, const std::string& value,
2490 const std::string& extParamKey)
2491 {
2492 if (locale.empty()) {
2493 HILOG_ERROR_I18N("LocaleConfig::ModifyExtParam: locale is empty.");
2494 return locale;
2495 }
2496 if (key.empty()) {
2497 HILOG_ERROR_I18N("LocaleConfig::ModifyExtParam: key is empty.");
2498 return locale;
2499 }
2500 std::unordered_map<std::string, std::string> paramMap;
2501 std::string localeBase = locale;
2502 std::vector<std::pair<size_t, std::string>> positions = GetExtParamPositions(locale);
2503 if (positions[0].first != std::string::npos) {
2504 localeBase = locale.substr(0, positions[0].first);
2505 }
2506 std::unordered_map<std::string, std::unordered_map<std::string, std::string>> extParamMap =
2507 ParseAllExtParam(locale);
2508 extParamMap[extParamKey][key] = value;
2509 std::string result = localeBase + GenerateAllExtParam(extParamMap);
2510 return result;
2511 }
2512
ParseAllExtParam(std::string locale)2513 std::unordered_map<std::string, std::unordered_map<std::string, std::string>> LocaleConfig::ParseAllExtParam(
2514 std::string locale)
2515 {
2516 std::unordered_map<std::string, std::unordered_map<std::string, std::string>> allExtParamMap;
2517 std::vector<std::pair<size_t, std::string>> positions = GetExtParamPositions(locale);
2518 std::reverse(positions.begin(), positions.end());
2519 for (size_t i = 0; i < positions.size(); i++) {
2520 size_t pos = positions[i].first;
2521 if (pos == std::string::npos) {
2522 continue;
2523 }
2524 std::string extParam = locale.substr(pos);
2525 locale = locale.substr(0, pos);
2526 std::string extParamKey = positions[i].second;
2527 std::unordered_map<std::string, std::string> extParamMap = ParseExtParam(extParam, extParamKey);
2528 allExtParamMap.insert(std::make_pair(extParamKey, extParamMap));
2529 }
2530 return allExtParamMap;
2531 }
2532
ParseExtParam(const std::string & extParam,const std::string & extParamKey)2533 std::unordered_map<std::string, std::string> LocaleConfig::ParseExtParam(const std::string& extParam,
2534 const std::string& extParamKey)
2535 {
2536 std::unordered_map<std::string, std::string> result;
2537 size_t pos = extParam.find(extParamKey);
2538 if (pos == std::string::npos) {
2539 HILOG_ERROR_I18N("LocaleConfig::ParseExtParam: extParam is invalid.");
2540 return result;
2541 }
2542 std::string param = extParam.substr(pos + extParamKey.length());
2543 std::vector<std::string> paramArray;
2544 Split(param, "-", paramArray);
2545 size_t pairLen = 2;
2546 if (paramArray.size() % pairLen != 0) {
2547 HILOG_ERROR_I18N("LocaleConfig::ParseExtParam: parse ext param failed.");
2548 return result;
2549 }
2550 for (size_t pos = 0; pos + 1 < paramArray.size(); pos += pairLen) {
2551 std::string key = paramArray[pos];
2552 std::string value = paramArray[pos + 1];
2553 if (key.empty() || value.empty()) {
2554 HILOG_ERROR_I18N("LocaleConfig::ParseExtParam: key or value is empty.");
2555 continue;
2556 }
2557 auto status = result.insert({key, value});
2558 if (!status.second) {
2559 HILOG_ERROR_I18N("LocaleConfig::ParseExtParam: insert key (%{public}s) and value (%{public}s) failed.",
2560 key.c_str(), value.c_str());
2561 }
2562 }
2563 return result;
2564 }
2565
GenerateAllExtParam(const std::unordered_map<std::string,std::unordered_map<std::string,std::string>> & extParamMap)2566 std::string LocaleConfig::GenerateAllExtParam(
2567 const std::unordered_map<std::string, std::unordered_map<std::string, std::string>>& extParamMap)
2568 {
2569 std::string extParam;
2570 auto it = extParamMap.find(STANDARD_EXT_PARAM_KEY);
2571 if (it != extParamMap.end()) {
2572 std::string standardExtParam = GenerateExtParam(it->second, STANDARD_EXT_PARAM_KEY);
2573 extParam += standardExtParam;
2574 }
2575 it = extParamMap.find(CUST_EXT_PARAM_KEY);
2576 if (it != extParamMap.end()) {
2577 std::string custExtParam = GenerateExtParam(it->second, CUST_EXT_PARAM_KEY);
2578 extParam += custExtParam;
2579 }
2580 return extParam;
2581 }
2582
GenerateExtParam(const std::unordered_map<std::string,std::string> & extParamMap,const std::string & extParamKey)2583 std::string LocaleConfig::GenerateExtParam(const std::unordered_map<std::string, std::string>& extParamMap,
2584 const std::string& extParamKey)
2585 {
2586 std::string extParam;
2587 for (auto& item : extParamMap) {
2588 std::string key = item.first;
2589 std::string value = item.second;
2590 if (value.empty()) {
2591 continue;
2592 }
2593 extParam += "-" + key + "-" + value;
2594 }
2595 if (!extParam.empty()) {
2596 extParam = extParamKey + extParam.substr(1);
2597 }
2598 return extParam;
2599 }
2600
GetExtParamPositions(const std::string & locale)2601 std::vector<std::pair<size_t, std::string>> LocaleConfig::GetExtParamPositions(const std::string& locale)
2602 {
2603 std::vector<std::pair<size_t, std::string>> result;
2604 size_t standardPosition = locale.find(STANDARD_EXT_PARAM_KEY);
2605 size_t custPosition = locale.find(CUST_EXT_PARAM_KEY);
2606 if (standardPosition != std::string::npos && custPosition != std::string::npos) {
2607 if (standardPosition < custPosition) {
2608 result.emplace_back(std::make_pair(standardPosition, STANDARD_EXT_PARAM_KEY));
2609 result.emplace_back(std::make_pair(custPosition, CUST_EXT_PARAM_KEY));
2610 } else {
2611 result.emplace_back(std::make_pair(custPosition, CUST_EXT_PARAM_KEY));
2612 result.emplace_back(std::make_pair(standardPosition, STANDARD_EXT_PARAM_KEY));
2613 }
2614 return result;
2615 }
2616 if (standardPosition == std::string::npos) {
2617 result.emplace_back(std::make_pair(custPosition, CUST_EXT_PARAM_KEY));
2618 result.emplace_back(std::make_pair(standardPosition, STANDARD_EXT_PARAM_KEY));
2619 return result;
2620 }
2621 result.emplace_back(std::make_pair(standardPosition, STANDARD_EXT_PARAM_KEY));
2622 result.emplace_back(std::make_pair(custPosition, CUST_EXT_PARAM_KEY));
2623 return result;
2624 }
2625
GetNumberingSystemDigit(const std::string & NumberingSystem)2626 std::string LocaleConfig::GetNumberingSystemDigit(const std::string& NumberingSystem)
2627 {
2628 auto it = NUMBERING_SYSTEM_NAME_TO_DESCRIPTION.find(NumberingSystem);
2629 if (it == NUMBERING_SYSTEM_NAME_TO_DESCRIPTION.end()) {
2630 HILOG_ERROR_I18N("LocaleConfig::GetNumberingSystemDigit: NumberingSystem is %{public}s.",
2631 NumberingSystem.c_str());
2632 return "";
2633 }
2634 return it->second;
2635 }
2636
GetSimplifiedLanguage(const std::string & languageTag,int32_t & code)2637 std::string LocaleConfig::GetSimplifiedLanguage(const std::string& languageTag, int32_t &code)
2638 {
2639 std::string simplifiedLanguage = "";
2640 if (IsValidTag(languageTag)) {
2641 LocaleInfo localeInfo(languageTag);
2642 simplifiedLanguage = localeInfo.Minimize();
2643 } else {
2644 code = 1;
2645 }
2646 return simplifiedLanguage;
2647 }
2648
GetSimplifiedSystemLanguage()2649 std::string LocaleConfig::GetSimplifiedSystemLanguage()
2650 {
2651 std::string locale = GetSystemLanguage();
2652 LocaleInfo localeInfo(locale);
2653 LocaleInfo localeInfoMax(localeInfo.Maximize());
2654 std::string language = localeInfoMax.GetLanguage();
2655 language = language + '-' + localeInfoMax.GetScript();
2656 if (dialectLanguages.find(language) != dialectLanguages.end()) {
2657 std::string systemRegion = localeInfo.GetRegion();
2658 if (!systemRegion.empty() && language.compare("en-Latn") != 0) {
2659 locale = language + '-' + systemRegion;
2660 } else {
2661 locale = GetSystemLocale();
2662 }
2663 LocaleInfo* requestLocale = new(std::nothrow) LocaleInfo(locale);
2664 if (requestLocale == nullptr) {
2665 HILOG_ERROR_I18N("GetSimplifiedLanguage: %{public}s failed to construct LocaleInfo.", locale.c_str());
2666 return "";
2667 }
2668 std::vector<LocaleInfo*> candidateLocales;
2669 for (auto& candidate : dialectLanguages[language]) {
2670 LocaleInfo* candidateInfo = new(std::nothrow) LocaleInfo(candidate);
2671 if (candidateInfo == nullptr) {
2672 HILOG_ERROR_I18N("GetSimplifiedLanguage: %{public}s failed to construct LocaleInfo.",
2673 candidate.c_str());
2674 continue;
2675 }
2676 candidateLocales.push_back(candidateInfo);
2677 }
2678 locale = LocaleMatcher::GetBestMatchedLocale(requestLocale, candidateLocales);
2679
2680 for (LocaleInfo* candidateInfo : candidateLocales) {
2681 delete candidateInfo;
2682 candidateInfo = nullptr;
2683 }
2684 delete requestLocale;
2685 requestLocale = nullptr;
2686 }
2687 LocaleInfo simplifiedLocale(locale);
2688 std::string ret = simplifiedLocale.Minimize();
2689 auto iter = resourceIdMap.find(ret);
2690 if (iter != resourceIdMap.end()) {
2691 ret = iter->second;
2692 }
2693 return ret;
2694 }
2695
GetUnicodeWrappedFilePath(const std::string & path,const char delimiter,std::shared_ptr<LocaleInfo> localeInfo,std::string & invalidField)2696 std::string LocaleConfig::GetUnicodeWrappedFilePath(const std::string &path, const char delimiter,
2697 std::shared_ptr<LocaleInfo> localeInfo, std::string &invalidField)
2698 {
2699 std::string locale;
2700 if (localeInfo != nullptr) {
2701 locale = localeInfo->GetBaseName();
2702 }
2703 return LocaleConfig::GetUnicodeWrappedFilePathInner(path, delimiter, locale, invalidField);
2704 }
2705
GetUnicodeWrappedFilePath(const std::string & path,const char delimiter,const std::string & localeTag,std::string & invalidField)2706 std::string LocaleConfig::GetUnicodeWrappedFilePath(const std::string &path, const char delimiter,
2707 const std::string& localeTag, std::string &invalidField)
2708 {
2709 std::string locale = LocaleConfig::RemoveAllExtParam(localeTag);
2710 return LocaleConfig::GetUnicodeWrappedFilePathInner(path, delimiter, locale, invalidField);
2711 }
2712
GetUnicodeWrappedFilePathInner(const std::string & path,const char delimiter,const std::string & localeTag,std::string & invalidField)2713 std::string LocaleConfig::GetUnicodeWrappedFilePathInner(const std::string &path, const char delimiter,
2714 const std::string& localeTag, std::string &invalidField)
2715 {
2716 if (delimiter == '\0') {
2717 invalidField = "delimiter";
2718 return path;
2719 }
2720 if (path.empty() || path.length() > PATH_MAX) {
2721 invalidField = "path";
2722 return path;
2723 }
2724 std::string locale = localeTag;
2725 if (!IsValidTag(locale)) {
2726 locale = GetSystemLocale();
2727 }
2728 if (!IsRTL(locale)) {
2729 return path;
2730 }
2731 std::string result;
2732 std::vector<string> dest;
2733 std::string sep(1, delimiter); // 1 is char count
2734 Split(path, sep, dest);
2735 if (dest.size() == 1) { // 1 is array's size
2736 return path;
2737 }
2738 for (size_t i = 0 ; i < dest.size(); i++) {
2739 if (dest[i].empty()) {
2740 continue;
2741 }
2742 if (i == 0 && dest[i].compare(sep) != 0) {
2743 dest[i] = "\u200f\u200e" + dest[i] + "\u200e";
2744 continue;
2745 }
2746 dest[i] = "\u200e" + dest[i] + "\u200e";
2747 }
2748 std::string newSep = "\u200f" + sep;
2749 Merge(dest, newSep, result);
2750 return result;
2751 }
2752
GetSystemLocaleInstanceTag()2753 std::string LocaleConfig::GetSystemLocaleInstanceTag()
2754 {
2755 return LocaleConfig::GetEffectiveLocale();
2756 }
2757
GetIcuLocale(const std::string & localeTag)2758 icu::Locale LocaleConfigExt::GetIcuLocale(const std::string& localeTag)
2759 {
2760 if (!LocaleConfig::IsValidTag(localeTag)) {
2761 return LocaleConfigExt::GetSystemIcuLocale();
2762 }
2763 UErrorCode status = U_ZERO_ERROR;
2764 icu::Locale locale = icu::Locale::forLanguageTag(localeTag, status);
2765 if (U_FAILURE(status)) {
2766 HILOG_ERROR_I18N("LocaleConfig::GetIcuLocale: Create icu locale failed.");
2767 return LocaleConfigExt::GetSystemIcuLocale();
2768 }
2769 return locale;
2770 }
2771
GetSystemIcuLocale()2772 icu::Locale LocaleConfigExt::GetSystemIcuLocale()
2773 {
2774 UErrorCode status = U_ZERO_ERROR;
2775 icu::Locale locale = icu::Locale::forLanguageTag(LocaleConfig::GetEffectiveLanguage(), status);
2776 if (U_FAILURE(status)) {
2777 HILOG_ERROR_I18N("LocaleConfigExt::GetSystemIcuLocale: Create icu locale failed.");
2778 }
2779 return locale;
2780 }
2781 } // namespace I18n
2782 } // namespace Global
2783 } // namespace OHOS
2784