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 if (validLocales != nullptr) {
36 for (int i = 0; i < validCount; i++) {
37 allValidLocales.insert(validLocales[i].getLanguage());
38 }
39 }
40 allValidLocales.insert("in");
41 allValidLocales.insert("iw");
42 allValidLocales.insert("tl");
43 return allValidLocales;
44 }
45
ResetFinalLocaleStatus()46 void LocaleInfo::ResetFinalLocaleStatus()
47 {
48 finalLocaleTag = "";
49 calendar = "";
50 collation = "";
51 hourCycle = "";
52 numberingSystem = "";
53 numeric = "";
54 caseFirst = "";
55 configs = {};
56 }
57
InitLocaleInfo(const std::string & localeTag,std::map<std::string,std::string> & configMap)58 void LocaleInfo::InitLocaleInfo(const std::string &localeTag, std::map<std::string, std::string> &configMap)
59 {
60 UErrorCode status = U_ZERO_ERROR;
61 configs = configMap;
62 if (localeTag != "") {
63 ComputeFinalLocaleTag(localeTag);
64 locale = icu::Locale::forLanguageTag(icu::StringPiece(finalLocaleTag), status);
65 }
66 if (localeTag == "" || status != U_ZERO_ERROR) {
67 std::string defaultLocaleTag = LocaleConfig::GetSystemLocale();
68 ResetFinalLocaleStatus();
69 ComputeFinalLocaleTag(defaultLocaleTag);
70 status = U_ZERO_ERROR;
71 locale = icu::Locale::forLanguageTag(icu::StringPiece(finalLocaleTag), status);
72 }
73 if (status == U_ZERO_ERROR) {
74 localeStatus = true;
75 language = locale.getLanguage();
76 script = locale.getScript();
77 region = locale.getCountry();
78 baseName = locale.getBaseName();
79 std::replace(baseName.begin(), baseName.end(), '_', '-');
80 }
81 }
82
LocaleInfo(const std::string & localeTag)83 LocaleInfo::LocaleInfo(const std::string &localeTag)
84 {
85 std::map<std::string, std::string> configMap;
86 InitLocaleInfo(localeTag, configMap);
87 }
88
LocaleInfo(const std::string & localeTag,std::map<std::string,std::string> & configMap)89 LocaleInfo::LocaleInfo(const std::string &localeTag, std::map<std::string, std::string> &configMap)
90 {
91 InitLocaleInfo(localeTag, configMap);
92 }
93
~LocaleInfo()94 LocaleInfo::~LocaleInfo() {}
95
ComputeFinalLocaleTag(const std::string & localeTag)96 void LocaleInfo::ComputeFinalLocaleTag(const std::string &localeTag)
97 {
98 if (localeTag.find("-u-") == std::string::npos) {
99 finalLocaleTag = localeTag;
100 ParseConfigs();
101 } else {
102 finalLocaleTag = localeTag.substr(0, localeTag.find("-u-"));
103 ParseLocaleTag(localeTag);
104 ParseConfigs();
105 }
106 if (!script.empty()) {
107 finalLocaleTag += "-" + script;
108 }
109 if (!region.empty()) {
110 finalLocaleTag += "-" + region;
111 }
112 if (!hourCycle.empty() || !numberingSystem.empty() || !calendar.empty() || !collation.empty() ||
113 !caseFirst.empty() || !numeric.empty()) {
114 finalLocaleTag += "-u";
115 }
116 if (!hourCycle.empty()) {
117 finalLocaleTag += hourCycleTag + hourCycle;
118 }
119 if (!numberingSystem.empty()) {
120 finalLocaleTag += numberingSystemTag + numberingSystem;
121 }
122 if (!calendar.empty()) {
123 finalLocaleTag += calendarTag + calendar;
124 }
125 if (!collation.empty()) {
126 finalLocaleTag += collationTag + collation;
127 }
128 if (!caseFirst.empty()) {
129 finalLocaleTag += caseFirstTag + caseFirst;
130 }
131 if (!numeric.empty()) {
132 finalLocaleTag += numericTag + numeric;
133 }
134 }
135
ParseLocaleTag(const std::string & localeTag)136 void LocaleInfo::ParseLocaleTag(const std::string &localeTag)
137 {
138 std::string flag = "-";
139 if (localeTag.find(hourCycleTag) != std::string::npos) {
140 hourCycle = localeTag.substr(localeTag.find(hourCycleTag) + CONFIG_TAG_LEN);
141 hourCycle = hourCycle.substr(0, hourCycle.find(flag));
142 }
143 if (localeTag.find(numberingSystemTag) != std::string::npos) {
144 numberingSystem = localeTag.substr(localeTag.find(numberingSystemTag) + CONFIG_TAG_LEN);
145 numberingSystem = numberingSystem.substr(0, numberingSystem.find(flag));
146 }
147 if (localeTag.find(calendarTag) != std::string::npos) {
148 calendar = localeTag.substr(localeTag.find(calendarTag) + CONFIG_TAG_LEN);
149 calendar = calendar.substr(0, calendar.find(flag));
150 }
151 if (localeTag.find(collationTag) != std::string::npos) {
152 collation = localeTag.substr(localeTag.find(collationTag) + CONFIG_TAG_LEN);
153 collation = collation.substr(0, collation.find(flag));
154 }
155 if (localeTag.find(caseFirstTag) != std::string::npos) {
156 caseFirst = localeTag.substr(localeTag.find(caseFirstTag) + CONFIG_TAG_LEN);
157 caseFirst = caseFirst.substr(0, caseFirst.find(flag));
158 }
159 if (localeTag.find(numericTag) != std::string::npos) {
160 numeric = localeTag.substr(localeTag.find(numericTag) + CONFIG_TAG_LEN);
161 numeric = numeric.substr(0, numeric.find(flag));
162 }
163 }
164
ParseConfigs()165 void LocaleInfo::ParseConfigs()
166 {
167 if (configs.count("script") > 0) {
168 script = configs["script"];
169 }
170 if (configs.count("region") > 0) {
171 region = configs["region"];
172 }
173 if (configs.count("hourCycle") > 0) {
174 hourCycle = configs["hourCycle"];
175 }
176 if (configs.count("numberingSystem") > 0) {
177 numberingSystem = configs["numberingSystem"];
178 }
179 if (configs.count("calendar") > 0) {
180 calendar = configs["calendar"];
181 }
182 if (configs.count("collation") > 0) {
183 collation = configs["collation"];
184 }
185 if (configs.count("caseFirst") > 0) {
186 caseFirst = configs["caseFirst"];
187 }
188 if (configs.count("numeric") > 0) {
189 numeric = configs["numeric"];
190 }
191 }
192
193 bool LocaleInfo::icuInitialized = LocaleInfo::Init();
194
GetLanguage() const195 std::string LocaleInfo::GetLanguage() const
196 {
197 return language;
198 }
199
GetScript() const200 std::string LocaleInfo::GetScript() const
201 {
202 return script;
203 }
204
GetRegion() const205 std::string LocaleInfo::GetRegion() const
206 {
207 return region;
208 }
209
GetBaseName() const210 std::string LocaleInfo::GetBaseName() const
211 {
212 return baseName;
213 }
214
GetCalendar() const215 std::string LocaleInfo::GetCalendar() const
216 {
217 return calendar;
218 }
219
GetCollation() const220 std::string LocaleInfo::GetCollation() const
221 {
222 return collation;
223 }
224
GetHourCycle() const225 std::string LocaleInfo::GetHourCycle() const
226 {
227 return hourCycle;
228 }
229
GetNumberingSystem() const230 std::string LocaleInfo::GetNumberingSystem() const
231 {
232 return numberingSystem;
233 }
234
GetNumeric() const235 std::string LocaleInfo::GetNumeric() const
236 {
237 return numeric;
238 }
239
GetCaseFirst() const240 std::string LocaleInfo::GetCaseFirst() const
241 {
242 return caseFirst;
243 }
244
ToString() const245 std::string LocaleInfo::ToString() const
246 {
247 return finalLocaleTag;
248 }
249
GetLocale() const250 Locale LocaleInfo::GetLocale() const
251 {
252 return locale;
253 }
254
Maximize()255 std::string LocaleInfo::Maximize()
256 {
257 if (!localeStatus) {
258 return "";
259 }
260 UErrorCode status = U_ZERO_ERROR;
261 Locale curLocale = locale;
262 curLocale.addLikelySubtags(status);
263 if (status == U_ZERO_ERROR) {
264 std::string restConfigs = "";
265 if (finalLocaleTag.find("-u-") != std::string::npos) {
266 restConfigs = finalLocaleTag.substr(finalLocaleTag.find("-u-"));
267 }
268 std::string curBaseName = (!curLocale.getBaseName()) ? "" : curLocale.getBaseName();
269 std::replace(curBaseName.begin(), curBaseName.end(), '_', '-');
270 std::string localeTag = curBaseName + restConfigs;
271 return localeTag;
272 }
273 return finalLocaleTag;
274 }
275
Minimize()276 std::string LocaleInfo::Minimize()
277 {
278 if (!localeStatus) {
279 return "";
280 }
281 UErrorCode status = U_ZERO_ERROR;
282 Locale curLocale = locale;
283 curLocale.minimizeSubtags(status);
284 if (status == U_ZERO_ERROR) {
285 std::string restConfigs = "";
286 if (finalLocaleTag.find("-u-") != std::string::npos) {
287 restConfigs = finalLocaleTag.substr(finalLocaleTag.find("-u-"));
288 }
289 std::string curBaseName = (!curLocale.getBaseName()) ? "" : curLocale.getBaseName();
290 std::replace(curBaseName.begin(), curBaseName.end(), '_', '-');
291 std::string localeTag = curBaseName + restConfigs;
292 return localeTag;
293 }
294 return finalLocaleTag;
295 }
296
Init()297 bool LocaleInfo::Init()
298 {
299 SetHwIcuDirectory();
300 return true;
301 }
302
InitSuccess() const303 bool LocaleInfo::InitSuccess() const
304 {
305 return localeStatus;
306 }
307 } // namespace I18n
308 } // namespace Global
309 } // namespace OHOS
310