1 /*
2 * Copyright (c) 2021 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
16 #include "algorithm"
17 #include "locale_config.h"
18 #include "map"
19 #include "memory"
20 #include "ohos/init_data.h"
21 #include "set"
22 #include "locale_info.h"
23
24 namespace OHOS {
25 namespace Global {
26 namespace I18n {
27 using namespace icu;
28 std::set<std::string> LocaleInfo::allValidLocales = GetValidLocales();
29
GetValidLocales()30 std::set<std::string> LocaleInfo::GetValidLocales()
31 {
32 int32_t validCount = 1;
33 const Locale *validLocales = Locale::getAvailableLocales(validCount);
34 std::set<std::string> allValidLocales;
35 for (int i = 0; i < validCount; i++) {
36 allValidLocales.insert(validLocales[i].getLanguage());
37 }
38 allValidLocales.insert("in");
39 allValidLocales.insert("iw");
40 allValidLocales.insert("tl");
41 return allValidLocales;
42 }
43
ResetFinalLocaleStatus()44 void LocaleInfo::ResetFinalLocaleStatus()
45 {
46 finalLocaleTag = "";
47 calendar = "";
48 collation = "";
49 hourCycle = "";
50 numberingSystem = "";
51 numeric = "";
52 caseFirst = "";
53 configs = {};
54 }
55
InitLocaleInfo(const std::string & localeTag,std::map<std::string,std::string> & configMap)56 void LocaleInfo::InitLocaleInfo(const std::string &localeTag, std::map<std::string, std::string> &configMap)
57 {
58 UErrorCode status = U_ZERO_ERROR;
59 configs = configMap;
60 if (localeTag != "") {
61 ComputeFinalLocaleTag(localeTag);
62 locale = icu::Locale::forLanguageTag(icu::StringPiece(finalLocaleTag), status);
63 }
64 if (localeTag == "" || status != U_ZERO_ERROR) {
65 std::string defaultLocaleTag = LocaleConfig::GetSystemLocale();
66 ResetFinalLocaleStatus();
67 ComputeFinalLocaleTag(defaultLocaleTag);
68 status = U_ZERO_ERROR;
69 locale = icu::Locale::forLanguageTag(icu::StringPiece(finalLocaleTag), status);
70 }
71 if (status == U_ZERO_ERROR) {
72 localeStatus = true;
73 language = locale.getLanguage();
74 script = locale.getScript();
75 region = locale.getCountry();
76 baseName = locale.getBaseName();
77 std::replace(baseName.begin(), baseName.end(), '_', '-');
78 }
79 }
80
LocaleInfo(const std::string & localeTag)81 LocaleInfo::LocaleInfo(const std::string &localeTag)
82 {
83 std::map<std::string, std::string> configMap;
84 InitLocaleInfo(localeTag, configMap);
85 }
86
LocaleInfo(const std::string & localeTag,std::map<std::string,std::string> & configMap)87 LocaleInfo::LocaleInfo(const std::string &localeTag, std::map<std::string, std::string> &configMap)
88 {
89 InitLocaleInfo(localeTag, configMap);
90 }
91
~LocaleInfo()92 LocaleInfo::~LocaleInfo() {}
93
ComputeFinalLocaleTag(const std::string & localeTag)94 void LocaleInfo::ComputeFinalLocaleTag(const std::string &localeTag)
95 {
96 if (localeTag.find("-u-") == std::string::npos) {
97 finalLocaleTag = localeTag;
98 ParseConfigs();
99 } else {
100 finalLocaleTag = localeTag.substr(0, localeTag.find("-u-"));
101 ParseLocaleTag(localeTag);
102 ParseConfigs();
103 }
104 if (!script.empty()) {
105 finalLocaleTag += "-" + script;
106 }
107 if (!region.empty()) {
108 finalLocaleTag += "-" + region;
109 }
110 if (!hourCycle.empty() || !numberingSystem.empty() || !calendar.empty() || !collation.empty() ||
111 !caseFirst.empty() || !numeric.empty()) {
112 finalLocaleTag += "-u";
113 }
114 if (!hourCycle.empty()) {
115 finalLocaleTag += hourCycleTag + hourCycle;
116 }
117 if (!numberingSystem.empty()) {
118 finalLocaleTag += numberingSystemTag + numberingSystem;
119 }
120 if (!calendar.empty()) {
121 finalLocaleTag += calendarTag + calendar;
122 }
123 if (!collation.empty()) {
124 finalLocaleTag += collationTag + collation;
125 }
126 if (!caseFirst.empty()) {
127 finalLocaleTag += caseFirstTag + caseFirst;
128 }
129 if (!numeric.empty()) {
130 finalLocaleTag += numericTag + numeric;
131 }
132 }
133
ParseLocaleTag(const std::string & localeTag)134 void LocaleInfo::ParseLocaleTag(const std::string &localeTag)
135 {
136 std::string flag = "-";
137 if (localeTag.find(hourCycleTag) != std::string::npos) {
138 hourCycle = localeTag.substr(localeTag.find(hourCycleTag) + CONFIG_TAG_LEN);
139 hourCycle = hourCycle.substr(0, hourCycle.find(flag));
140 }
141 if (localeTag.find(numberingSystemTag) != std::string::npos) {
142 numberingSystem = localeTag.substr(localeTag.find(numberingSystemTag) + CONFIG_TAG_LEN);
143 numberingSystem = numberingSystem.substr(0, numberingSystem.find(flag));
144 }
145 if (localeTag.find(calendarTag) != std::string::npos) {
146 calendar = localeTag.substr(localeTag.find(calendarTag) + CONFIG_TAG_LEN);
147 calendar = calendar.substr(0, calendar.find(flag));
148 }
149 if (localeTag.find(collationTag) != std::string::npos) {
150 collation = localeTag.substr(localeTag.find(collationTag) + CONFIG_TAG_LEN);
151 collation = collation.substr(0, collation.find(flag));
152 }
153 if (localeTag.find(caseFirstTag) != std::string::npos) {
154 caseFirst = localeTag.substr(localeTag.find(caseFirstTag) + CONFIG_TAG_LEN);
155 caseFirst = caseFirst.substr(0, caseFirst.find(flag));
156 }
157 if (localeTag.find(numericTag) != std::string::npos) {
158 numeric = localeTag.substr(localeTag.find(numericTag) + CONFIG_TAG_LEN);
159 numeric = numeric.substr(0, numeric.find(flag));
160 }
161 }
162
ParseConfigs()163 void LocaleInfo::ParseConfigs()
164 {
165 if (configs.count("script") > 0) {
166 script = configs["script"];
167 }
168 if (configs.count("region") > 0) {
169 region = configs["region"];
170 }
171 if (configs.count("hourCycle") > 0) {
172 hourCycle = configs["hourCycle"];
173 }
174 if (configs.count("numberingSystem") > 0) {
175 numberingSystem = configs["numberingSystem"];
176 }
177 if (configs.count("calendar") > 0) {
178 calendar = configs["calendar"];
179 }
180 if (configs.count("collation") > 0) {
181 collation = configs["collation"];
182 }
183 if (configs.count("caseFirst") > 0) {
184 caseFirst = configs["caseFirst"];
185 }
186 if (configs.count("numeric") > 0) {
187 numeric = configs["numeric"];
188 }
189 }
190
191 bool LocaleInfo::icuInitialized = LocaleInfo::Init();
192
GetLanguage() const193 std::string LocaleInfo::GetLanguage() const
194 {
195 return language;
196 }
197
GetScript() const198 std::string LocaleInfo::GetScript() const
199 {
200 return script;
201 }
202
GetRegion() const203 std::string LocaleInfo::GetRegion() const
204 {
205 return region;
206 }
207
GetBaseName() const208 std::string LocaleInfo::GetBaseName() const
209 {
210 return baseName;
211 }
212
GetCalendar() const213 std::string LocaleInfo::GetCalendar() const
214 {
215 return calendar;
216 }
217
GetCollation() const218 std::string LocaleInfo::GetCollation() const
219 {
220 return collation;
221 }
222
GetHourCycle() const223 std::string LocaleInfo::GetHourCycle() const
224 {
225 return hourCycle;
226 }
227
GetNumberingSystem() const228 std::string LocaleInfo::GetNumberingSystem() const
229 {
230 return numberingSystem;
231 }
232
GetNumeric() const233 std::string LocaleInfo::GetNumeric() const
234 {
235 return numeric;
236 }
237
GetCaseFirst() const238 std::string LocaleInfo::GetCaseFirst() const
239 {
240 return caseFirst;
241 }
242
ToString() const243 std::string LocaleInfo::ToString() const
244 {
245 return finalLocaleTag;
246 }
247
GetLocale() const248 Locale LocaleInfo::GetLocale() const
249 {
250 return locale;
251 }
252
Maximize()253 std::string LocaleInfo::Maximize()
254 {
255 if (!localeStatus) {
256 return "";
257 }
258 UErrorCode status = U_ZERO_ERROR;
259 Locale curLocale = locale;
260 curLocale.addLikelySubtags(status);
261 if (status == U_ZERO_ERROR) {
262 std::string restConfigs = "";
263 if (finalLocaleTag.find("-u-") != std::string::npos) {
264 restConfigs = finalLocaleTag.substr(finalLocaleTag.find("-u-"));
265 }
266 std::string curBaseName = (!curLocale.getBaseName()) ? "" : curLocale.getBaseName();
267 std::replace(curBaseName.begin(), curBaseName.end(), '_', '-');
268 std::string localeTag = curBaseName + restConfigs;
269 return localeTag;
270 }
271 return finalLocaleTag;
272 }
273
Minimize()274 std::string LocaleInfo::Minimize()
275 {
276 if (!localeStatus) {
277 return "";
278 }
279 UErrorCode status = U_ZERO_ERROR;
280 Locale curLocale = locale;
281 curLocale.minimizeSubtags(status);
282 if (status == U_ZERO_ERROR) {
283 std::string restConfigs = "";
284 if (finalLocaleTag.find("-u-") != std::string::npos) {
285 restConfigs = finalLocaleTag.substr(finalLocaleTag.find("-u-"));
286 }
287 std::string curBaseName = (!curLocale.getBaseName()) ? "" : curLocale.getBaseName();
288 std::replace(curBaseName.begin(), curBaseName.end(), '_', '-');
289 std::string localeTag = curBaseName + restConfigs;
290 return localeTag;
291 }
292 return finalLocaleTag;
293 }
294
Init()295 bool LocaleInfo::Init()
296 {
297 SetHwIcuDirectory();
298 return true;
299 }
300
InitSuccess() const301 bool LocaleInfo::InitSuccess() const
302 {
303 return localeStatus;
304 }
305 } // namespace I18n
306 } // namespace Global
307 } // namespace OHOS
308