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 
16 #ifndef FOUNDATION_ACE_FRAMEWORKS_BASE_I18N_LOCALIZATION_H
17 #define FOUNDATION_ACE_FRAMEWORKS_BASE_I18N_LOCALIZATION_H
18 
19 #include <cstdint>
20 #include <functional>
21 #include <future>
22 #include <memory>
23 #include <mutex>
24 #include <new>
25 #include <string>
26 #include <vector>
27 
28 #include "base/utils/date_util.h"
29 #include "base/utils/macros.h"
30 #include "base/utils/noncopyable.h"
31 
32 namespace OHOS::Ace {
33 
34 struct LocaleProxy;
35 
36 struct LunarDate : Date {
37     bool isLeapMonth = false;
38 
39     bool operator==(const LunarDate& lunarDate) const
40     {
41         if (lunarDate.isLeapMonth != isLeapMonth) {
42             return false;
43         }
44         return (lunarDate.year == year && lunarDate.month == month && lunarDate.day == day);
45     }
46 
47     bool operator!=(const LunarDate& lunarDate) const
48     {
49         return !operator==(lunarDate);
50     }
51 };
52 
53 struct DateTime final : Date {
54     uint32_t hour = 0;
55     uint32_t minute = 0;
56     uint32_t second = 0;
57 };
58 
59 enum DateTimeStyle { NONE, FULL, LONG, MEDIUM, SHORT };
60 
61 enum MeasureFormatStyle { WIDTH_WIDE, WIDTH_SHORT, WIDTH_NARROW, WIDTH_NUMERIC, WIDTH_COUNT };
62 
63 enum TimeUnitStyle { YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, MILLISECOND };
64 
65 class ACE_FORCE_EXPORT Localization : public NonCopyable {
66 public:
67     /**
68      * Get language list to select the best language.
69      * @return language list which is supported
70      */
71     virtual ~Localization();
72     static const std::vector<std::string>& GetLanguageList(const std::string& language);
73 
74     static std::shared_ptr<Localization> GetInstance();
75 
76     static void SetLocale(const std::string& language, const std::string& countryOrRegion, const std::string& script,
77         const std::string& selectLanguage, const std::string& keywordsAndValues);
78 
79     static std::string ComputeScript(const std::string& language, const std::string& region);
80 
81     static void ParseLocaleTag(const std::string& languageTag, std::string& language, std::string& script,
82         std::string& region, bool needAddSubtags);
83 
SetOnChange(const std::function<void ()> & value)84     void SetOnChange(const std::function<void()>& value)
85     {
86         onChange_ = value;
87     }
88 
HandleOnChange()89     void HandleOnChange()
90     {
91         if (onChange_) {
92             onChange_();
93         }
94     }
95 
SetOnMymrChange(const std::function<void (bool)> & value)96     void SetOnMymrChange(const std::function<void(bool)>& value)
97     {
98         onMymrChange_ = value;
99     }
100 
GetOnMymrChange()101     const std::function<void(bool)>& GetOnMymrChange() const
102     {
103         return onMymrChange_;
104     }
105 
HandleOnMymrChange(bool isZawgyiMyanmar)106     void HandleOnMymrChange(bool isZawgyiMyanmar)
107     {
108         if (onMymrChange_) {
109             onMymrChange_(isZawgyiMyanmar);
110         }
111     }
112 
113     bool GetDateColumnFormatOrder(std::vector<std::string>& outOrder);
114 
115     bool GetDateOrder(std::vector<std::string>& outOrder);
116 
IsAmPmHour()117     bool IsAmPmHour()
118     {
119         bool isAmPm = false;
120         bool hasZero = true;
121         GetHourFormat(isAmPm, hasZero);
122         return isAmPm;
123     }
124 
HasZeroHour()125     bool HasZeroHour()
126     {
127         bool isAmPm = false;
128         bool hasZero = true;
129         GetHourFormat(isAmPm, hasZero);
130         return hasZero;
131     }
132 
133     std::string GetLanguage();
134     std::string GetLanguageTag();
135     std::string GetFontLocale();
136 
137     /**
138      * For formatting local format duration. Cannot be formatted correctly when duration greater than 24
139      * hours. For example: 10:00.
140      * @param duration    The value used to set the duration, the range is 0 to 90,000.
141      * @return local format duration.
142      */
143     const std::string FormatDuration(uint32_t duration, bool needShowHour = false);
144 
145     /**
146      * For formatting local format duration. Cannot be formatted correctly when duration greater than 24
147      * hours. For example: 10:00.
148      * @param duration    The value used to set the duration, the range is 0 to 90,000.
149      * @param format      the pattern for the format.For example: HH-mm-ss-SS.
150      * @return local format duration.
151      */
152     std::string FormatDuration(uint32_t duration, const std::string& format);
153 
154     /**
155      * For formatting date time. For example: 2020/03/30 08:00:00.
156      * @param dateTime    The value of date time.
157      * @param format      the pattern for the format.
158      * @return local format date time.
159      */
160     const std::string FormatDateTime(DateTime dateTime, const std::string& format);
161 
162     /**
163      * For formatting date time.
164      * @param dateTime     The value of date time.
165      * @param dateStyle    The value of date style.
166      * @param timeStyle    The value of time style.
167      * @return local format date time.
168      */
169     const std::string FormatDateTime(DateTime dateTime, DateTimeStyle dateStyle, DateTimeStyle timeStyle);
170 
171     /**
172      * Gets month strings. For example: "January", "February", etc.
173      * @param isShortType    The month style.
174      * @param calendarType   The calendar style.
175      * @return the month string vector.
176      */
177     std::vector<std::string> GetMonths(bool isShortType = false, const std::string& calendarType = "");
178 
179     /**
180      * Gets weekdays strings. For example: "Monday", "Tuesday", etc.
181      * @param isShortType    The weekday style.
182      * @return the weekday string vector.
183      */
184     std::vector<std::string> GetWeekdays(bool isShortType = false);
185 
186     /**
187      * Gets AM/PM strings. For example: "AM", "PM".
188      * @return the AM/PM string vector.
189      */
190     std::vector<std::string> GetAmPmStrings();
191 
192     /**
193      * Gets relative date. For example: "yesterday", "today", "tomorrow", "in 2 days", etc.
194      * @param offset    The relative date time offset.
195      * @return the relative date string.
196      */
197     std::string GetRelativeDateTime(double offset);
198 
199     /**
200      * Gets lunar date.
201      * @param date the western calendar date.
202      * @return the lunar calendar date.
203      */
204     LunarDate GetLunarDate(Date date);
205 
206     /**
207      * Gets lunar month.
208      * @param month the western calendar month.
209      * @param isLeapMonth is a leap month.
210      * @return the lunar calendar month.
211      */
212     std::string GetLunarMonth(uint32_t month, bool isLeapMonth);
213 
214     /**
215      * Gets lunar day.
216      * @param dayOfMonth the western calendar day.
217      * @return the lunar calendar day.
218      */
219     std::string GetLunarDay(uint32_t dayOfMonth);
220 
221     /**
222      * For formatting time unit. For example: "8hours", "8min", etc .
223      * @param timeValue the format time value.
224      * @param timeStyle the time unit style.
225      * @param formatStyle the measure format style.
226      * @return local format time unit.
227      */
228     std::string TimeUnitFormat(double timeValue, TimeUnitStyle timeStyle, MeasureFormatStyle formatStyle);
229 
230     /**
231      * For formatting plural rules.
232      * @param number the number to be formatted.
233      * @param isCardinal the plural is cardinal type.
234      * @return local keyword of the plural rule.
235      */
236     std::string PluralRulesFormat(double number, bool isCardinal = true);
237 
238     /**
239      * Gets Letter strings for indexer. For example: "A", "B", etc.
240      * @return the letter string vector.
241      */
242     std::vector<std::u16string> GetIndexLetter();
243 
244     /**
245      * For formatting number.
246      * @param number the number to be formatted.
247      * @return local format number.
248      */
249     std::string NumberFormat(double number);
250 
251     /**
252      * Gets alphabet strings. For example: "A", "B", etc.
253      * @return the alphabet string vector.
254      */
255     std::vector<std::u16string> GetIndexAlphabet();
256 
257     /**
258      * Gets entry letters, read from resource/binary/entry.json.
259      * @param lettersIndex letters index, like "common.ok"
260      * @return letters
261      */
262     std::string GetEntryLetters(const std::string& lettersIndex);
263 
264     /**
265      * Gets error description, read from resource/binary/errorcode.json.
266      * @param errorIndex error index, like "error_video_000001"
267      * @return error description
268      */
269     std::string GetErrorDescription(const std::string& errorIndex);
270 
271 private:
272     void SetLocaleImpl(const std::string& language, const std::string& countryOrRegion, const std::string& script,
273         const std::string& selectLanguage, const std::string& keywordsAndValues);
274     std::vector<std::u16string> GetLetters(bool alphabet);
275     bool GetHourFormat(bool& isAmPm, bool& hasZero);
276     bool Contain(const std::string& str, const std::string& tag);
277     LunarDate GetIcuLunarDate(Date date);
278 
279     std::unique_ptr<LocaleProxy> locale_;
280     std::string languageTag_;
281     std::string selectLanguage_;
282     std::string fontLocale_;
283 
284     std::promise<bool> promise_;
285     std::shared_future<bool> future_ = promise_.get_future();
286     std::function<void()> onChange_;
287     std::function<void(bool)> onMymrChange_;
288     bool isPromiseUsed_ = false;
289     bool isInit_ = false;
290 
WaitingForInit()291     void WaitingForInit()
292     {
293         if (!isInit_) {
294             isInit_ = future_.get();
295         }
296     }
297 
298     static std::mutex mutex_;
299     static std::shared_ptr<Localization> instance_;
300     static bool firstInstance_;
301 };
302 
303 } // namespace OHOS::Ace
304 
305 #endif // FOUNDATION_ACE_FRAMEWORKS_BASE_I18N_LOCALIZATION_H
306