1 /*
2 * Copyright (c) 2021-2022 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 "preferred_language.h"
16
17 #include "locale_config.h"
18 #include "locale_info.h"
19 #include "parameter.h"
20 #include "vector"
21
22
23 namespace OHOS {
24 namespace Global {
25 namespace I18n {
26 const char *PreferredLanguage::RESOURCE_PATH_HEAD = "/data/accounts/account_0/applications/";
27 const char *PreferredLanguage::RESOURCE_PATH_TAILOR = "/assets/entry/resources.index";
28 const char *PreferredLanguage::RESOURCE_PATH_SPLITOR = "/";
29 const char *PreferredLanguage::PREFERRED_LANGUAGES = "persist.sys.preferredLanguages";
30
AddPreferredLanguageExist(std::vector<std::string> & preferredLanguageList,int languageIdx,int index,const std::string & language)31 bool PreferredLanguage::AddPreferredLanguageExist(std::vector<std::string> &preferredLanguageList, int languageIdx,
32 int index, const std::string& language)
33 {
34 if (languageIdx == index) {
35 return false;
36 }
37 if (languageIdx < index) {
38 for (int i = languageIdx; i < index; i++) {
39 preferredLanguageList[i] = preferredLanguageList[i + 1];
40 }
41 }
42 if (languageIdx > index) {
43 for (int i = languageIdx; i > index; i--) {
44 preferredLanguageList[i] = preferredLanguageList[i - 1];
45 }
46 }
47 preferredLanguageList[index] = language;
48 if (!languageIdx || !index) {
49 bool status = LocaleConfig::SetSystemLanguage(preferredLanguageList[0]);
50 if (!status) {
51 return false;
52 }
53 }
54 return true;
55 }
56
AddPreferredLanguageNonExist(std::vector<std::string> & preferredLanguageList,int index,const std::string & language)57 bool PreferredLanguage::AddPreferredLanguageNonExist(std::vector<std::string> &preferredLanguageList, int index,
58 const std::string& language)
59 {
60 preferredLanguageList.insert(preferredLanguageList.begin() + index, language);
61 if (!index) {
62 bool status = LocaleConfig::SetSystemLanguage(preferredLanguageList[0]);
63 if (!status) {
64 return false;
65 }
66 }
67 return true;
68 }
69
AddPreferredLanguage(const std::string & language,int index)70 bool PreferredLanguage::AddPreferredLanguage(const std::string &language, int index)
71 {
72 if (!LocaleConfig::CheckPermission()) {
73 return false;
74 }
75 if (!IsValidTag(language)) {
76 return false;
77 }
78 std::vector<std::string> preferredLanguageList = GetPreferredLanguageList();
79 int idx = index;
80 if (index < 0) {
81 idx = 0;
82 }
83 if (index >= (int)preferredLanguageList.size()) {
84 idx = (int)preferredLanguageList.size();
85 }
86 int languageIdx = -1;
87 for (size_t i = 0; i < preferredLanguageList.size(); i++) {
88 if (preferredLanguageList[i] == language) {
89 languageIdx = (int)i;
90 break;
91 }
92 }
93 bool status = true;
94 if (languageIdx == -1) {
95 status = AddPreferredLanguageNonExist(preferredLanguageList, idx, language);
96 } else {
97 if (idx == (int)preferredLanguageList.size()) {
98 idx -= 1;
99 }
100 status = AddPreferredLanguageExist(preferredLanguageList, languageIdx, idx, language);
101 }
102 if (!status) {
103 return false;
104 }
105 std::string result = "";
106 for (size_t i = 0; i < preferredLanguageList.size(); i++) {
107 result += preferredLanguageList[i];
108 result += ";";
109 }
110 result.pop_back();
111 if (result.length() > CONFIG_LEN) {
112 return false;
113 }
114 status = SetParameter(PREFERRED_LANGUAGES, result.data()) == 0;
115 return status;
116 }
117
RemovePreferredLanguage(int index)118 bool PreferredLanguage::RemovePreferredLanguage(int index)
119 {
120 if (!LocaleConfig::CheckPermission()) {
121 return false;
122 }
123 std::vector<std::string> preferredLanguageList = GetPreferredLanguageList();
124 int idx = index;
125 if (index < 0) {
126 idx = 0;
127 }
128 if (index >= (int)preferredLanguageList.size()) {
129 idx = (int)preferredLanguageList.size() - 1;
130 }
131 if (preferredLanguageList.size() == 1) {
132 return false;
133 }
134 std::vector<std::string>::iterator it = preferredLanguageList.begin();
135 preferredLanguageList.erase(it + idx);
136 bool status = false;
137 if (!idx) {
138 status = LocaleConfig::SetSystemLanguage(preferredLanguageList[0]);
139 if (!status) {
140 return false;
141 }
142 }
143 std::string result = "";
144 for (it = preferredLanguageList.begin(); it != preferredLanguageList.end(); ++it) {
145 result += *it;
146 result += ";";
147 }
148 result.pop_back();
149 status = SetParameter(PREFERRED_LANGUAGES, result.data()) == 0;
150 return status;
151 }
152
GetPreferredLanguageList()153 std::vector<std::string> PreferredLanguage::GetPreferredLanguageList()
154 {
155 char preferredLanguageValue[CONFIG_LEN];
156 GetParameter(PREFERRED_LANGUAGES, "", preferredLanguageValue, CONFIG_LEN);
157 std::string systemLanguage = LocaleConfig::GetSystemLanguage();
158 std::vector<std::string> list;
159 Split(preferredLanguageValue, ";", list);
160 if (!list.size()) {
161 if (systemLanguage != "") {
162 list.push_back(systemLanguage);
163 }
164 return list;
165 }
166 if (list[0] == systemLanguage || systemLanguage == "") {
167 return list;
168 }
169 int systemLanguageIdx = -1;
170 for (size_t i = 0; i < list.size(); i++) {
171 if (list[i] == systemLanguage) {
172 systemLanguageIdx = (int)i;
173 }
174 }
175 if (systemLanguageIdx == -1) {
176 list.insert(list.begin(), systemLanguage);
177 } else {
178 for (size_t i = (size_t)systemLanguageIdx; i > 0; i--) {
179 list[i] = list[i - 1];
180 }
181 list[0] = systemLanguage;
182 }
183 return list;
184 }
185
IsMatched(const std::string & preferred,const std::string & resource)186 bool PreferredLanguage::IsMatched(const std::string& preferred, const std::string& resource)
187 {
188 LocaleInfo preferredLocaleInfo(preferred);
189 LocaleInfo resourceLocaleInfo(resource);
190 if (preferred == resource) {
191 return true;
192 }
193 if (preferredLocaleInfo.GetLanguage() != resourceLocaleInfo.GetLanguage()) {
194 return false;
195 }
196 LocaleInfo maximizedResourceLocale(resourceLocaleInfo.Maximize());
197 std::string resourceScript = maximizedResourceLocale.GetScript();
198 if (resourceScript == "") {
199 std::string resourceCountry = maximizedResourceLocale.GetRegion();
200 if (resourceCountry == "") {
201 return true;
202 }
203 std::string preferredCountry = preferredLocaleInfo.GetRegion();
204 if (resourceCountry == preferredCountry) {
205 return true;
206 }
207 return false;
208 }
209 LocaleInfo maximizedPreferredLocale(preferredLocaleInfo.Maximize());
210 std::string preferredScript = maximizedResourceLocale.GetScript();
211 if (resourceScript == preferredScript) {
212 return true;
213 }
214 return false;
215 }
216
GetFirstPreferredLanguage()217 std::string PreferredLanguage::GetFirstPreferredLanguage()
218 {
219 std::vector<std::string> preferredLanguageList = GetPreferredLanguageList();
220 return preferredLanguageList[0];
221 }
222
GetPreferredLocale()223 std::string PreferredLanguage::GetPreferredLocale()
224 {
225 std::string systemLocale = LocaleConfig::GetSystemLocale();
226 LocaleInfo systemLocaleInfo(systemLocale);
227 std::string systemRegion = systemLocaleInfo.GetRegion();
228 std::string preferredLanguageLocale = GetFirstPreferredLanguage();
229 LocaleInfo preferredLanguageLocaleInfo(preferredLanguageLocale);
230 std::string preferredLanguage = preferredLanguageLocaleInfo.GetLanguage();
231 std::string preferredLocale = preferredLanguage + "-" + systemRegion;
232 return preferredLocale;
233 }
234
IsValidLanguage(const std::string & language)235 bool PreferredLanguage::IsValidLanguage(const std::string &language)
236 {
237 std::string::size_type size = language.size();
238 if ((size != LANGUAGE_LEN) && (size != LANGUAGE_LEN + 1)) {
239 return false;
240 }
241 for (size_t i = 0; i < size; ++i) {
242 if ((language[i] > 'z') || (language[i] < 'a')) {
243 return false;
244 }
245 }
246 return true;
247 }
248
IsValidTag(const std::string & tag)249 bool PreferredLanguage::IsValidTag(const std::string &tag)
250 {
251 if (!tag.size()) {
252 return false;
253 }
254 std::vector<std::string> splits;
255 Split(tag, "-", splits);
256 if (!IsValidLanguage(splits[0])) {
257 return false;
258 }
259 return true;
260 }
261
Split(const std::string & src,const std::string & sep,std::vector<std::string> & dest)262 void PreferredLanguage::Split(const std::string &src, const std::string &sep, std::vector<std::string> &dest)
263 {
264 std::string::size_type begin = 0;
265 std::string::size_type end = src.find(sep);
266 while (end != std::string::npos) {
267 dest.push_back(src.substr(begin, end - begin));
268 begin = end + sep.size();
269 end = src.find(sep, begin);
270 }
271 if (begin != src.size()) {
272 dest.push_back(src.substr(begin));
273 }
274 }
275 } // namespace I18n
276 } // namespace Global
277 } // namespace OHOS