jpayne@69
|
1 // © 2019 and later: Unicode, Inc. and others.
|
jpayne@69
|
2 // License & terms of use: http://www.unicode.org/copyright.html#License
|
jpayne@69
|
3
|
jpayne@69
|
4 // localematcher.h
|
jpayne@69
|
5 // created: 2019may08 Markus W. Scherer
|
jpayne@69
|
6
|
jpayne@69
|
7 #ifndef __LOCALEMATCHER_H__
|
jpayne@69
|
8 #define __LOCALEMATCHER_H__
|
jpayne@69
|
9
|
jpayne@69
|
10 #include "unicode/utypes.h"
|
jpayne@69
|
11
|
jpayne@69
|
12 #if U_SHOW_CPLUSPLUS_API
|
jpayne@69
|
13
|
jpayne@69
|
14 #include "unicode/locid.h"
|
jpayne@69
|
15 #include "unicode/stringpiece.h"
|
jpayne@69
|
16 #include "unicode/uobject.h"
|
jpayne@69
|
17
|
jpayne@69
|
18 /**
|
jpayne@69
|
19 * \file
|
jpayne@69
|
20 * \brief C++ API: Locale matcher: User's desired locales vs. application's supported locales.
|
jpayne@69
|
21 */
|
jpayne@69
|
22
|
jpayne@69
|
23 #ifndef U_FORCE_HIDE_DRAFT_API
|
jpayne@69
|
24
|
jpayne@69
|
25 /**
|
jpayne@69
|
26 * Builder option for whether the language subtag or the script subtag is most important.
|
jpayne@69
|
27 *
|
jpayne@69
|
28 * @see Builder#setFavorSubtag(ULocMatchFavorSubtag)
|
jpayne@69
|
29 * @draft ICU 65
|
jpayne@69
|
30 */
|
jpayne@69
|
31 enum ULocMatchFavorSubtag {
|
jpayne@69
|
32 /**
|
jpayne@69
|
33 * Language differences are most important, then script differences, then region differences.
|
jpayne@69
|
34 * (This is the default behavior.)
|
jpayne@69
|
35 *
|
jpayne@69
|
36 * @draft ICU 65
|
jpayne@69
|
37 */
|
jpayne@69
|
38 ULOCMATCH_FAVOR_LANGUAGE,
|
jpayne@69
|
39 /**
|
jpayne@69
|
40 * Makes script differences matter relatively more than language differences.
|
jpayne@69
|
41 *
|
jpayne@69
|
42 * @draft ICU 65
|
jpayne@69
|
43 */
|
jpayne@69
|
44 ULOCMATCH_FAVOR_SCRIPT
|
jpayne@69
|
45 };
|
jpayne@69
|
46 #ifndef U_IN_DOXYGEN
|
jpayne@69
|
47 typedef enum ULocMatchFavorSubtag ULocMatchFavorSubtag;
|
jpayne@69
|
48 #endif
|
jpayne@69
|
49
|
jpayne@69
|
50 /**
|
jpayne@69
|
51 * Builder option for whether all desired locales are treated equally or
|
jpayne@69
|
52 * earlier ones are preferred.
|
jpayne@69
|
53 *
|
jpayne@69
|
54 * @see Builder#setDemotionPerDesiredLocale(ULocMatchDemotion)
|
jpayne@69
|
55 * @draft ICU 65
|
jpayne@69
|
56 */
|
jpayne@69
|
57 enum ULocMatchDemotion {
|
jpayne@69
|
58 /**
|
jpayne@69
|
59 * All desired locales are treated equally.
|
jpayne@69
|
60 *
|
jpayne@69
|
61 * @draft ICU 65
|
jpayne@69
|
62 */
|
jpayne@69
|
63 ULOCMATCH_DEMOTION_NONE,
|
jpayne@69
|
64 /**
|
jpayne@69
|
65 * Earlier desired locales are preferred.
|
jpayne@69
|
66 *
|
jpayne@69
|
67 * <p>From each desired locale to the next,
|
jpayne@69
|
68 * the distance to any supported locale is increased by an additional amount
|
jpayne@69
|
69 * which is at least as large as most region mismatches.
|
jpayne@69
|
70 * A later desired locale has to have a better match with some supported locale
|
jpayne@69
|
71 * due to more than merely having the same region subtag.
|
jpayne@69
|
72 *
|
jpayne@69
|
73 * <p>For example: <code>Supported={en, sv} desired=[en-GB, sv]</code>
|
jpayne@69
|
74 * yields <code>Result(en-GB, en)</code> because
|
jpayne@69
|
75 * with the demotion of sv its perfect match is no better than
|
jpayne@69
|
76 * the region distance between the earlier desired locale en-GB and en=en-US.
|
jpayne@69
|
77 *
|
jpayne@69
|
78 * <p>Notes:
|
jpayne@69
|
79 * <ul>
|
jpayne@69
|
80 * <li>In some cases, language and/or script differences can be as small as
|
jpayne@69
|
81 * the typical region difference. (Example: sr-Latn vs. sr-Cyrl)
|
jpayne@69
|
82 * <li>It is possible for certain region differences to be larger than usual,
|
jpayne@69
|
83 * and larger than the demotion.
|
jpayne@69
|
84 * (As of CLDR 35 there is no such case, but
|
jpayne@69
|
85 * this is possible in future versions of the data.)
|
jpayne@69
|
86 * </ul>
|
jpayne@69
|
87 *
|
jpayne@69
|
88 * @draft ICU 65
|
jpayne@69
|
89 */
|
jpayne@69
|
90 ULOCMATCH_DEMOTION_REGION
|
jpayne@69
|
91 };
|
jpayne@69
|
92 #ifndef U_IN_DOXYGEN
|
jpayne@69
|
93 typedef enum ULocMatchDemotion ULocMatchDemotion;
|
jpayne@69
|
94 #endif
|
jpayne@69
|
95
|
jpayne@69
|
96 /**
|
jpayne@69
|
97 * Builder option for whether to include or ignore one-way (fallback) match data.
|
jpayne@69
|
98 * The LocaleMatcher uses CLDR languageMatch data which includes fallback (oneway=true) entries.
|
jpayne@69
|
99 * Sometimes it is desirable to ignore those.
|
jpayne@69
|
100 *
|
jpayne@69
|
101 * <p>For example, consider a web application with the UI in a given language,
|
jpayne@69
|
102 * with a link to another, related web app.
|
jpayne@69
|
103 * The link should include the UI language, and the target server may also use
|
jpayne@69
|
104 * the client’s Accept-Language header data.
|
jpayne@69
|
105 * The target server has its own list of supported languages.
|
jpayne@69
|
106 * One may want to favor UI language consistency, that is,
|
jpayne@69
|
107 * if there is a decent match for the original UI language, we want to use it,
|
jpayne@69
|
108 * but not if it is merely a fallback.
|
jpayne@69
|
109 *
|
jpayne@69
|
110 * @see Builder#setDirection(ULocMatchDirection)
|
jpayne@69
|
111 * @draft ICU 67
|
jpayne@69
|
112 */
|
jpayne@69
|
113 enum ULocMatchDirection {
|
jpayne@69
|
114 /**
|
jpayne@69
|
115 * Locale matching includes one-way matches such as Breton→French. (default)
|
jpayne@69
|
116 *
|
jpayne@69
|
117 * @draft ICU 67
|
jpayne@69
|
118 */
|
jpayne@69
|
119 ULOCMATCH_DIRECTION_WITH_ONE_WAY,
|
jpayne@69
|
120 /**
|
jpayne@69
|
121 * Locale matching limited to two-way matches including e.g. Danish↔Norwegian
|
jpayne@69
|
122 * but ignoring one-way matches.
|
jpayne@69
|
123 *
|
jpayne@69
|
124 * @draft ICU 67
|
jpayne@69
|
125 */
|
jpayne@69
|
126 ULOCMATCH_DIRECTION_ONLY_TWO_WAY
|
jpayne@69
|
127 };
|
jpayne@69
|
128 #ifndef U_IN_DOXYGEN
|
jpayne@69
|
129 typedef enum ULocMatchDirection ULocMatchDirection;
|
jpayne@69
|
130 #endif
|
jpayne@69
|
131
|
jpayne@69
|
132 struct UHashtable;
|
jpayne@69
|
133
|
jpayne@69
|
134 U_NAMESPACE_BEGIN
|
jpayne@69
|
135
|
jpayne@69
|
136 struct LSR;
|
jpayne@69
|
137
|
jpayne@69
|
138 class LocaleDistance;
|
jpayne@69
|
139 class LocaleLsrIterator;
|
jpayne@69
|
140 class UVector;
|
jpayne@69
|
141 class XLikelySubtags;
|
jpayne@69
|
142
|
jpayne@69
|
143 /**
|
jpayne@69
|
144 * Immutable class that picks the best match between a user's desired locales and
|
jpayne@69
|
145 * an application's supported locales.
|
jpayne@69
|
146 * Movable but not copyable.
|
jpayne@69
|
147 *
|
jpayne@69
|
148 * <p>Example:
|
jpayne@69
|
149 * <pre>
|
jpayne@69
|
150 * UErrorCode errorCode = U_ZERO_ERROR;
|
jpayne@69
|
151 * LocaleMatcher matcher = LocaleMatcher::Builder().setSupportedLocales("fr, en-GB, en").build(errorCode);
|
jpayne@69
|
152 * Locale *bestSupported = matcher.getBestLocale(Locale.US, errorCode); // "en"
|
jpayne@69
|
153 * </pre>
|
jpayne@69
|
154 *
|
jpayne@69
|
155 * <p>A matcher takes into account when languages are close to one another,
|
jpayne@69
|
156 * such as Danish and Norwegian,
|
jpayne@69
|
157 * and when regional variants are close, like en-GB and en-AU as opposed to en-US.
|
jpayne@69
|
158 *
|
jpayne@69
|
159 * <p>If there are multiple supported locales with the same (language, script, region)
|
jpayne@69
|
160 * likely subtags, then the current implementation returns the first of those locales.
|
jpayne@69
|
161 * It ignores variant subtags (except for pseudolocale variants) and extensions.
|
jpayne@69
|
162 * This may change in future versions.
|
jpayne@69
|
163 *
|
jpayne@69
|
164 * <p>For example, the current implementation does not distinguish between
|
jpayne@69
|
165 * de, de-DE, de-Latn, de-1901, de-u-co-phonebk.
|
jpayne@69
|
166 *
|
jpayne@69
|
167 * <p>If you prefer one equivalent locale over another, then provide only the preferred one,
|
jpayne@69
|
168 * or place it earlier in the list of supported locales.
|
jpayne@69
|
169 *
|
jpayne@69
|
170 * <p>Otherwise, the order of supported locales may have no effect on the best-match results.
|
jpayne@69
|
171 * The current implementation compares each desired locale with supported locales
|
jpayne@69
|
172 * in the following order:
|
jpayne@69
|
173 * 1. Default locale, if supported;
|
jpayne@69
|
174 * 2. CLDR "paradigm locales" like en-GB and es-419;
|
jpayne@69
|
175 * 3. other supported locales.
|
jpayne@69
|
176 * This may change in future versions.
|
jpayne@69
|
177 *
|
jpayne@69
|
178 * <p>Often a product will just need one matcher instance, built with the languages
|
jpayne@69
|
179 * that it supports. However, it may want multiple instances with different
|
jpayne@69
|
180 * default languages based on additional information, such as the domain.
|
jpayne@69
|
181 *
|
jpayne@69
|
182 * <p>This class is not intended for public subclassing.
|
jpayne@69
|
183 *
|
jpayne@69
|
184 * @draft ICU 65
|
jpayne@69
|
185 */
|
jpayne@69
|
186 class U_COMMON_API LocaleMatcher : public UMemory {
|
jpayne@69
|
187 public:
|
jpayne@69
|
188 /**
|
jpayne@69
|
189 * Data for the best-matching pair of a desired and a supported locale.
|
jpayne@69
|
190 * Movable but not copyable.
|
jpayne@69
|
191 *
|
jpayne@69
|
192 * @draft ICU 65
|
jpayne@69
|
193 */
|
jpayne@69
|
194 class U_COMMON_API Result : public UMemory {
|
jpayne@69
|
195 public:
|
jpayne@69
|
196 /**
|
jpayne@69
|
197 * Move constructor; might modify the source.
|
jpayne@69
|
198 * This object will have the same contents that the source object had.
|
jpayne@69
|
199 *
|
jpayne@69
|
200 * @param src Result to move contents from.
|
jpayne@69
|
201 * @draft ICU 65
|
jpayne@69
|
202 */
|
jpayne@69
|
203 Result(Result &&src) U_NOEXCEPT;
|
jpayne@69
|
204
|
jpayne@69
|
205 /**
|
jpayne@69
|
206 * Destructor.
|
jpayne@69
|
207 *
|
jpayne@69
|
208 * @draft ICU 65
|
jpayne@69
|
209 */
|
jpayne@69
|
210 ~Result();
|
jpayne@69
|
211
|
jpayne@69
|
212 /**
|
jpayne@69
|
213 * Move assignment; might modify the source.
|
jpayne@69
|
214 * This object will have the same contents that the source object had.
|
jpayne@69
|
215 *
|
jpayne@69
|
216 * @param src Result to move contents from.
|
jpayne@69
|
217 * @draft ICU 65
|
jpayne@69
|
218 */
|
jpayne@69
|
219 Result &operator=(Result &&src) U_NOEXCEPT;
|
jpayne@69
|
220
|
jpayne@69
|
221 #ifndef U_HIDE_DRAFT_API
|
jpayne@69
|
222 /**
|
jpayne@69
|
223 * Returns the best-matching desired locale.
|
jpayne@69
|
224 * nullptr if the list of desired locales is empty or if none matched well enough.
|
jpayne@69
|
225 *
|
jpayne@69
|
226 * @return the best-matching desired locale, or nullptr.
|
jpayne@69
|
227 * @draft ICU 65
|
jpayne@69
|
228 */
|
jpayne@69
|
229 inline const Locale *getDesiredLocale() const { return desiredLocale; }
|
jpayne@69
|
230
|
jpayne@69
|
231 /**
|
jpayne@69
|
232 * Returns the best-matching supported locale.
|
jpayne@69
|
233 * If none matched well enough, this is the default locale.
|
jpayne@69
|
234 * The default locale is nullptr if the list of supported locales is empty and
|
jpayne@69
|
235 * no explicit default locale is set.
|
jpayne@69
|
236 *
|
jpayne@69
|
237 * @return the best-matching supported locale, or nullptr.
|
jpayne@69
|
238 * @draft ICU 65
|
jpayne@69
|
239 */
|
jpayne@69
|
240 inline const Locale *getSupportedLocale() const { return supportedLocale; }
|
jpayne@69
|
241
|
jpayne@69
|
242 /**
|
jpayne@69
|
243 * Returns the index of the best-matching desired locale in the input Iterable order.
|
jpayne@69
|
244 * -1 if the list of desired locales is empty or if none matched well enough.
|
jpayne@69
|
245 *
|
jpayne@69
|
246 * @return the index of the best-matching desired locale, or -1.
|
jpayne@69
|
247 * @draft ICU 65
|
jpayne@69
|
248 */
|
jpayne@69
|
249 inline int32_t getDesiredIndex() const { return desiredIndex; }
|
jpayne@69
|
250
|
jpayne@69
|
251 /**
|
jpayne@69
|
252 * Returns the index of the best-matching supported locale in the
|
jpayne@69
|
253 * constructor’s or builder’s input order (“set” Collection plus “added” locales).
|
jpayne@69
|
254 * If the matcher was built from a locale list string, then the iteration order is that
|
jpayne@69
|
255 * of a LocalePriorityList built from the same string.
|
jpayne@69
|
256 * -1 if the list of supported locales is empty or if none matched well enough.
|
jpayne@69
|
257 *
|
jpayne@69
|
258 * @return the index of the best-matching supported locale, or -1.
|
jpayne@69
|
259 * @draft ICU 65
|
jpayne@69
|
260 */
|
jpayne@69
|
261 inline int32_t getSupportedIndex() const { return supportedIndex; }
|
jpayne@69
|
262
|
jpayne@69
|
263 /**
|
jpayne@69
|
264 * Takes the best-matching supported locale and adds relevant fields of the
|
jpayne@69
|
265 * best-matching desired locale, such as the -t- and -u- extensions.
|
jpayne@69
|
266 * May replace some fields of the supported locale.
|
jpayne@69
|
267 * The result is the locale that should be used for date and number formatting, collation, etc.
|
jpayne@69
|
268 * Returns the root locale if getSupportedLocale() returns nullptr.
|
jpayne@69
|
269 *
|
jpayne@69
|
270 * <p>Example: desired=ar-SA-u-nu-latn, supported=ar-EG, resolved locale=ar-SA-u-nu-latn
|
jpayne@69
|
271 *
|
jpayne@69
|
272 * @return a locale combining the best-matching desired and supported locales.
|
jpayne@69
|
273 * @draft ICU 65
|
jpayne@69
|
274 */
|
jpayne@69
|
275 Locale makeResolvedLocale(UErrorCode &errorCode) const;
|
jpayne@69
|
276 #endif // U_HIDE_DRAFT_API
|
jpayne@69
|
277
|
jpayne@69
|
278 private:
|
jpayne@69
|
279 Result(const Locale *desired, const Locale *supported,
|
jpayne@69
|
280 int32_t desIndex, int32_t suppIndex, UBool owned) :
|
jpayne@69
|
281 desiredLocale(desired), supportedLocale(supported),
|
jpayne@69
|
282 desiredIndex(desIndex), supportedIndex(suppIndex),
|
jpayne@69
|
283 desiredIsOwned(owned) {}
|
jpayne@69
|
284
|
jpayne@69
|
285 Result(const Result &other) = delete;
|
jpayne@69
|
286 Result &operator=(const Result &other) = delete;
|
jpayne@69
|
287
|
jpayne@69
|
288 const Locale *desiredLocale;
|
jpayne@69
|
289 const Locale *supportedLocale;
|
jpayne@69
|
290 int32_t desiredIndex;
|
jpayne@69
|
291 int32_t supportedIndex;
|
jpayne@69
|
292 UBool desiredIsOwned;
|
jpayne@69
|
293
|
jpayne@69
|
294 friend class LocaleMatcher;
|
jpayne@69
|
295 };
|
jpayne@69
|
296
|
jpayne@69
|
297 /**
|
jpayne@69
|
298 * LocaleMatcher builder.
|
jpayne@69
|
299 * Movable but not copyable.
|
jpayne@69
|
300 *
|
jpayne@69
|
301 * @see LocaleMatcher#builder()
|
jpayne@69
|
302 * @draft ICU 65
|
jpayne@69
|
303 */
|
jpayne@69
|
304 class U_COMMON_API Builder : public UMemory {
|
jpayne@69
|
305 public:
|
jpayne@69
|
306 /**
|
jpayne@69
|
307 * Constructs a builder used in chaining parameters for building a LocaleMatcher.
|
jpayne@69
|
308 *
|
jpayne@69
|
309 * @return a new Builder object
|
jpayne@69
|
310 * @draft ICU 65
|
jpayne@69
|
311 */
|
jpayne@69
|
312 Builder() {}
|
jpayne@69
|
313
|
jpayne@69
|
314 /**
|
jpayne@69
|
315 * Move constructor; might modify the source.
|
jpayne@69
|
316 * This builder will have the same contents that the source builder had.
|
jpayne@69
|
317 *
|
jpayne@69
|
318 * @param src Builder to move contents from.
|
jpayne@69
|
319 * @draft ICU 65
|
jpayne@69
|
320 */
|
jpayne@69
|
321 Builder(Builder &&src) U_NOEXCEPT;
|
jpayne@69
|
322
|
jpayne@69
|
323 /**
|
jpayne@69
|
324 * Destructor.
|
jpayne@69
|
325 *
|
jpayne@69
|
326 * @draft ICU 65
|
jpayne@69
|
327 */
|
jpayne@69
|
328 ~Builder();
|
jpayne@69
|
329
|
jpayne@69
|
330 /**
|
jpayne@69
|
331 * Move assignment; might modify the source.
|
jpayne@69
|
332 * This builder will have the same contents that the source builder had.
|
jpayne@69
|
333 *
|
jpayne@69
|
334 * @param src Builder to move contents from.
|
jpayne@69
|
335 * @draft ICU 65
|
jpayne@69
|
336 */
|
jpayne@69
|
337 Builder &operator=(Builder &&src) U_NOEXCEPT;
|
jpayne@69
|
338
|
jpayne@69
|
339 #ifndef U_HIDE_DRAFT_API
|
jpayne@69
|
340 /**
|
jpayne@69
|
341 * Parses an Accept-Language string
|
jpayne@69
|
342 * (<a href="https://tools.ietf.org/html/rfc2616#section-14.4">RFC 2616 Section 14.4</a>),
|
jpayne@69
|
343 * such as "af, en, fr;q=0.9", and sets the supported locales accordingly.
|
jpayne@69
|
344 * Allows whitespace in more places but does not allow "*".
|
jpayne@69
|
345 * Clears any previously set/added supported locales first.
|
jpayne@69
|
346 *
|
jpayne@69
|
347 * @param locales the Accept-Language string of locales to set
|
jpayne@69
|
348 * @return this Builder object
|
jpayne@69
|
349 * @draft ICU 65
|
jpayne@69
|
350 */
|
jpayne@69
|
351 Builder &setSupportedLocalesFromListString(StringPiece locales);
|
jpayne@69
|
352
|
jpayne@69
|
353 /**
|
jpayne@69
|
354 * Copies the supported locales, preserving iteration order.
|
jpayne@69
|
355 * Clears any previously set/added supported locales first.
|
jpayne@69
|
356 * Duplicates are allowed, and are not removed.
|
jpayne@69
|
357 *
|
jpayne@69
|
358 * @param locales the list of locale
|
jpayne@69
|
359 * @return this Builder object
|
jpayne@69
|
360 * @draft ICU 65
|
jpayne@69
|
361 */
|
jpayne@69
|
362 Builder &setSupportedLocales(Locale::Iterator &locales);
|
jpayne@69
|
363
|
jpayne@69
|
364 /**
|
jpayne@69
|
365 * Copies the supported locales from the begin/end range, preserving iteration order.
|
jpayne@69
|
366 * Clears any previously set/added supported locales first.
|
jpayne@69
|
367 * Duplicates are allowed, and are not removed.
|
jpayne@69
|
368 *
|
jpayne@69
|
369 * Each of the iterator parameter values must be an
|
jpayne@69
|
370 * input iterator whose value is convertible to const Locale &.
|
jpayne@69
|
371 *
|
jpayne@69
|
372 * @param begin Start of range.
|
jpayne@69
|
373 * @param end Exclusive end of range.
|
jpayne@69
|
374 * @return this Builder object
|
jpayne@69
|
375 * @draft ICU 65
|
jpayne@69
|
376 */
|
jpayne@69
|
377 template<typename Iter>
|
jpayne@69
|
378 Builder &setSupportedLocales(Iter begin, Iter end) {
|
jpayne@69
|
379 if (U_FAILURE(errorCode_)) { return *this; }
|
jpayne@69
|
380 clearSupportedLocales();
|
jpayne@69
|
381 while (begin != end) {
|
jpayne@69
|
382 addSupportedLocale(*begin++);
|
jpayne@69
|
383 }
|
jpayne@69
|
384 return *this;
|
jpayne@69
|
385 }
|
jpayne@69
|
386
|
jpayne@69
|
387 /**
|
jpayne@69
|
388 * Copies the supported locales from the begin/end range, preserving iteration order.
|
jpayne@69
|
389 * Calls the converter to convert each *begin to a Locale or const Locale &.
|
jpayne@69
|
390 * Clears any previously set/added supported locales first.
|
jpayne@69
|
391 * Duplicates are allowed, and are not removed.
|
jpayne@69
|
392 *
|
jpayne@69
|
393 * Each of the iterator parameter values must be an
|
jpayne@69
|
394 * input iterator whose value is convertible to const Locale &.
|
jpayne@69
|
395 *
|
jpayne@69
|
396 * @param begin Start of range.
|
jpayne@69
|
397 * @param end Exclusive end of range.
|
jpayne@69
|
398 * @param converter Converter from *begin to const Locale & or compatible.
|
jpayne@69
|
399 * @return this Builder object
|
jpayne@69
|
400 * @draft ICU 65
|
jpayne@69
|
401 */
|
jpayne@69
|
402 template<typename Iter, typename Conv>
|
jpayne@69
|
403 Builder &setSupportedLocalesViaConverter(Iter begin, Iter end, Conv converter) {
|
jpayne@69
|
404 if (U_FAILURE(errorCode_)) { return *this; }
|
jpayne@69
|
405 clearSupportedLocales();
|
jpayne@69
|
406 while (begin != end) {
|
jpayne@69
|
407 addSupportedLocale(converter(*begin++));
|
jpayne@69
|
408 }
|
jpayne@69
|
409 return *this;
|
jpayne@69
|
410 }
|
jpayne@69
|
411
|
jpayne@69
|
412 /**
|
jpayne@69
|
413 * Adds another supported locale.
|
jpayne@69
|
414 * Duplicates are allowed, and are not removed.
|
jpayne@69
|
415 *
|
jpayne@69
|
416 * @param locale another locale
|
jpayne@69
|
417 * @return this Builder object
|
jpayne@69
|
418 * @draft ICU 65
|
jpayne@69
|
419 */
|
jpayne@69
|
420 Builder &addSupportedLocale(const Locale &locale);
|
jpayne@69
|
421
|
jpayne@69
|
422 /**
|
jpayne@69
|
423 * Sets the default locale; if nullptr, or if it is not set explicitly,
|
jpayne@69
|
424 * then the first supported locale is used as the default locale.
|
jpayne@69
|
425 *
|
jpayne@69
|
426 * @param defaultLocale the default locale (will be copied)
|
jpayne@69
|
427 * @return this Builder object
|
jpayne@69
|
428 * @draft ICU 65
|
jpayne@69
|
429 */
|
jpayne@69
|
430 Builder &setDefaultLocale(const Locale *defaultLocale);
|
jpayne@69
|
431
|
jpayne@69
|
432 /**
|
jpayne@69
|
433 * If ULOCMATCH_FAVOR_SCRIPT, then the language differences are smaller than script
|
jpayne@69
|
434 * differences.
|
jpayne@69
|
435 * This is used in situations (such as maps) where
|
jpayne@69
|
436 * it is better to fall back to the same script than a similar language.
|
jpayne@69
|
437 *
|
jpayne@69
|
438 * @param subtag the subtag to favor
|
jpayne@69
|
439 * @return this Builder object
|
jpayne@69
|
440 * @draft ICU 65
|
jpayne@69
|
441 */
|
jpayne@69
|
442 Builder &setFavorSubtag(ULocMatchFavorSubtag subtag);
|
jpayne@69
|
443
|
jpayne@69
|
444 /**
|
jpayne@69
|
445 * Option for whether all desired locales are treated equally or
|
jpayne@69
|
446 * earlier ones are preferred (this is the default).
|
jpayne@69
|
447 *
|
jpayne@69
|
448 * @param demotion the demotion per desired locale to set.
|
jpayne@69
|
449 * @return this Builder object
|
jpayne@69
|
450 * @draft ICU 65
|
jpayne@69
|
451 */
|
jpayne@69
|
452 Builder &setDemotionPerDesiredLocale(ULocMatchDemotion demotion);
|
jpayne@69
|
453
|
jpayne@69
|
454 /**
|
jpayne@69
|
455 * Option for whether to include or ignore one-way (fallback) match data.
|
jpayne@69
|
456 * By default, they are included.
|
jpayne@69
|
457 *
|
jpayne@69
|
458 * @param direction the match direction to set.
|
jpayne@69
|
459 * @return this Builder object
|
jpayne@69
|
460 * @draft ICU 67
|
jpayne@69
|
461 */
|
jpayne@69
|
462 Builder &setDirection(ULocMatchDirection direction) {
|
jpayne@69
|
463 if (U_SUCCESS(errorCode_)) {
|
jpayne@69
|
464 direction_ = direction;
|
jpayne@69
|
465 }
|
jpayne@69
|
466 return *this;
|
jpayne@69
|
467 }
|
jpayne@69
|
468
|
jpayne@69
|
469 /**
|
jpayne@69
|
470 * Sets the UErrorCode if an error occurred while setting parameters.
|
jpayne@69
|
471 * Preserves older error codes in the outErrorCode.
|
jpayne@69
|
472 *
|
jpayne@69
|
473 * @param outErrorCode Set to an error code if it does not contain one already
|
jpayne@69
|
474 * and an error occurred while setting parameters.
|
jpayne@69
|
475 * Otherwise unchanged.
|
jpayne@69
|
476 * @return TRUE if U_FAILURE(outErrorCode)
|
jpayne@69
|
477 * @draft ICU 65
|
jpayne@69
|
478 */
|
jpayne@69
|
479 UBool copyErrorTo(UErrorCode &outErrorCode) const;
|
jpayne@69
|
480
|
jpayne@69
|
481 /**
|
jpayne@69
|
482 * Builds and returns a new locale matcher.
|
jpayne@69
|
483 * This builder can continue to be used.
|
jpayne@69
|
484 *
|
jpayne@69
|
485 * @param errorCode ICU error code. Its input value must pass the U_SUCCESS() test,
|
jpayne@69
|
486 * or else the function returns immediately. Check for U_FAILURE()
|
jpayne@69
|
487 * on output or use with function chaining. (See User Guide for details.)
|
jpayne@69
|
488 * @return new LocaleMatcher.
|
jpayne@69
|
489 * @draft ICU 65
|
jpayne@69
|
490 */
|
jpayne@69
|
491 LocaleMatcher build(UErrorCode &errorCode) const;
|
jpayne@69
|
492 #endif // U_HIDE_DRAFT_API
|
jpayne@69
|
493
|
jpayne@69
|
494 private:
|
jpayne@69
|
495 friend class LocaleMatcher;
|
jpayne@69
|
496
|
jpayne@69
|
497 Builder(const Builder &other) = delete;
|
jpayne@69
|
498 Builder &operator=(const Builder &other) = delete;
|
jpayne@69
|
499
|
jpayne@69
|
500 void clearSupportedLocales();
|
jpayne@69
|
501 bool ensureSupportedLocaleVector();
|
jpayne@69
|
502
|
jpayne@69
|
503 UErrorCode errorCode_ = U_ZERO_ERROR;
|
jpayne@69
|
504 UVector *supportedLocales_ = nullptr;
|
jpayne@69
|
505 int32_t thresholdDistance_ = -1;
|
jpayne@69
|
506 ULocMatchDemotion demotion_ = ULOCMATCH_DEMOTION_REGION;
|
jpayne@69
|
507 Locale *defaultLocale_ = nullptr;
|
jpayne@69
|
508 ULocMatchFavorSubtag favor_ = ULOCMATCH_FAVOR_LANGUAGE;
|
jpayne@69
|
509 ULocMatchDirection direction_ = ULOCMATCH_DIRECTION_WITH_ONE_WAY;
|
jpayne@69
|
510 };
|
jpayne@69
|
511
|
jpayne@69
|
512 // FYI No public LocaleMatcher constructors in C++; use the Builder.
|
jpayne@69
|
513
|
jpayne@69
|
514 /**
|
jpayne@69
|
515 * Move copy constructor; might modify the source.
|
jpayne@69
|
516 * This matcher will have the same settings that the source matcher had.
|
jpayne@69
|
517 * @param src source matcher
|
jpayne@69
|
518 * @draft ICU 65
|
jpayne@69
|
519 */
|
jpayne@69
|
520 LocaleMatcher(LocaleMatcher &&src) U_NOEXCEPT;
|
jpayne@69
|
521
|
jpayne@69
|
522 /**
|
jpayne@69
|
523 * Destructor.
|
jpayne@69
|
524 * @draft ICU 65
|
jpayne@69
|
525 */
|
jpayne@69
|
526 ~LocaleMatcher();
|
jpayne@69
|
527
|
jpayne@69
|
528 /**
|
jpayne@69
|
529 * Move assignment operator; might modify the source.
|
jpayne@69
|
530 * This matcher will have the same settings that the source matcher had.
|
jpayne@69
|
531 * The behavior is undefined if *this and src are the same object.
|
jpayne@69
|
532 * @param src source matcher
|
jpayne@69
|
533 * @return *this
|
jpayne@69
|
534 * @draft ICU 65
|
jpayne@69
|
535 */
|
jpayne@69
|
536 LocaleMatcher &operator=(LocaleMatcher &&src) U_NOEXCEPT;
|
jpayne@69
|
537
|
jpayne@69
|
538 #ifndef U_HIDE_DRAFT_API
|
jpayne@69
|
539 /**
|
jpayne@69
|
540 * Returns the supported locale which best matches the desired locale.
|
jpayne@69
|
541 *
|
jpayne@69
|
542 * @param desiredLocale Typically a user's language.
|
jpayne@69
|
543 * @param errorCode ICU error code. Its input value must pass the U_SUCCESS() test,
|
jpayne@69
|
544 * or else the function returns immediately. Check for U_FAILURE()
|
jpayne@69
|
545 * on output or use with function chaining. (See User Guide for details.)
|
jpayne@69
|
546 * @return the best-matching supported locale.
|
jpayne@69
|
547 * @draft ICU 65
|
jpayne@69
|
548 */
|
jpayne@69
|
549 const Locale *getBestMatch(const Locale &desiredLocale, UErrorCode &errorCode) const;
|
jpayne@69
|
550
|
jpayne@69
|
551 /**
|
jpayne@69
|
552 * Returns the supported locale which best matches one of the desired locales.
|
jpayne@69
|
553 *
|
jpayne@69
|
554 * @param desiredLocales Typically a user's languages, in order of preference (descending).
|
jpayne@69
|
555 * @param errorCode ICU error code. Its input value must pass the U_SUCCESS() test,
|
jpayne@69
|
556 * or else the function returns immediately. Check for U_FAILURE()
|
jpayne@69
|
557 * on output or use with function chaining. (See User Guide for details.)
|
jpayne@69
|
558 * @return the best-matching supported locale.
|
jpayne@69
|
559 * @draft ICU 65
|
jpayne@69
|
560 */
|
jpayne@69
|
561 const Locale *getBestMatch(Locale::Iterator &desiredLocales, UErrorCode &errorCode) const;
|
jpayne@69
|
562
|
jpayne@69
|
563 /**
|
jpayne@69
|
564 * Parses an Accept-Language string
|
jpayne@69
|
565 * (<a href="https://tools.ietf.org/html/rfc2616#section-14.4">RFC 2616 Section 14.4</a>),
|
jpayne@69
|
566 * such as "af, en, fr;q=0.9",
|
jpayne@69
|
567 * and returns the supported locale which best matches one of the desired locales.
|
jpayne@69
|
568 * Allows whitespace in more places but does not allow "*".
|
jpayne@69
|
569 *
|
jpayne@69
|
570 * @param desiredLocaleList Typically a user's languages, as an Accept-Language string.
|
jpayne@69
|
571 * @param errorCode ICU error code. Its input value must pass the U_SUCCESS() test,
|
jpayne@69
|
572 * or else the function returns immediately. Check for U_FAILURE()
|
jpayne@69
|
573 * on output or use with function chaining. (See User Guide for details.)
|
jpayne@69
|
574 * @return the best-matching supported locale.
|
jpayne@69
|
575 * @draft ICU 65
|
jpayne@69
|
576 */
|
jpayne@69
|
577 const Locale *getBestMatchForListString(StringPiece desiredLocaleList, UErrorCode &errorCode) const;
|
jpayne@69
|
578
|
jpayne@69
|
579 /**
|
jpayne@69
|
580 * Returns the best match between the desired locale and the supported locales.
|
jpayne@69
|
581 * If the result's desired locale is not nullptr, then it is the address of the input locale.
|
jpayne@69
|
582 * It has not been cloned.
|
jpayne@69
|
583 *
|
jpayne@69
|
584 * @param desiredLocale Typically a user's language.
|
jpayne@69
|
585 * @param errorCode ICU error code. Its input value must pass the U_SUCCESS() test,
|
jpayne@69
|
586 * or else the function returns immediately. Check for U_FAILURE()
|
jpayne@69
|
587 * on output or use with function chaining. (See User Guide for details.)
|
jpayne@69
|
588 * @return the best-matching pair of the desired and a supported locale.
|
jpayne@69
|
589 * @draft ICU 65
|
jpayne@69
|
590 */
|
jpayne@69
|
591 Result getBestMatchResult(const Locale &desiredLocale, UErrorCode &errorCode) const;
|
jpayne@69
|
592
|
jpayne@69
|
593 /**
|
jpayne@69
|
594 * Returns the best match between the desired and supported locales.
|
jpayne@69
|
595 * If the result's desired locale is not nullptr, then it is a clone of
|
jpayne@69
|
596 * the best-matching desired locale. The Result object owns the clone.
|
jpayne@69
|
597 *
|
jpayne@69
|
598 * @param desiredLocales Typically a user's languages, in order of preference (descending).
|
jpayne@69
|
599 * @param errorCode ICU error code. Its input value must pass the U_SUCCESS() test,
|
jpayne@69
|
600 * or else the function returns immediately. Check for U_FAILURE()
|
jpayne@69
|
601 * on output or use with function chaining. (See User Guide for details.)
|
jpayne@69
|
602 * @return the best-matching pair of a desired and a supported locale.
|
jpayne@69
|
603 * @draft ICU 65
|
jpayne@69
|
604 */
|
jpayne@69
|
605 Result getBestMatchResult(Locale::Iterator &desiredLocales, UErrorCode &errorCode) const;
|
jpayne@69
|
606 #endif // U_HIDE_DRAFT_API
|
jpayne@69
|
607
|
jpayne@69
|
608 #ifndef U_HIDE_INTERNAL_API
|
jpayne@69
|
609 /**
|
jpayne@69
|
610 * Returns a fraction between 0 and 1, where 1 means that the languages are a
|
jpayne@69
|
611 * perfect match, and 0 means that they are completely different.
|
jpayne@69
|
612 *
|
jpayne@69
|
613 * <p>This is mostly an implementation detail, and the precise values may change over time.
|
jpayne@69
|
614 * The implementation may use either the maximized forms or the others ones, or both.
|
jpayne@69
|
615 * The implementation may or may not rely on the forms to be consistent with each other.
|
jpayne@69
|
616 *
|
jpayne@69
|
617 * <p>Callers should construct and use a matcher rather than match pairs of locales directly.
|
jpayne@69
|
618 *
|
jpayne@69
|
619 * @param desired Desired locale.
|
jpayne@69
|
620 * @param supported Supported locale.
|
jpayne@69
|
621 * @param errorCode ICU error code. Its input value must pass the U_SUCCESS() test,
|
jpayne@69
|
622 * or else the function returns immediately. Check for U_FAILURE()
|
jpayne@69
|
623 * on output or use with function chaining. (See User Guide for details.)
|
jpayne@69
|
624 * @return value between 0 and 1, inclusive.
|
jpayne@69
|
625 * @internal (has a known user)
|
jpayne@69
|
626 */
|
jpayne@69
|
627 double internalMatch(const Locale &desired, const Locale &supported, UErrorCode &errorCode) const;
|
jpayne@69
|
628 #endif // U_HIDE_INTERNAL_API
|
jpayne@69
|
629
|
jpayne@69
|
630 private:
|
jpayne@69
|
631 LocaleMatcher(const Builder &builder, UErrorCode &errorCode);
|
jpayne@69
|
632 LocaleMatcher(const LocaleMatcher &other) = delete;
|
jpayne@69
|
633 LocaleMatcher &operator=(const LocaleMatcher &other) = delete;
|
jpayne@69
|
634
|
jpayne@69
|
635 int32_t putIfAbsent(const LSR &lsr, int32_t i, int32_t suppLength, UErrorCode &errorCode);
|
jpayne@69
|
636
|
jpayne@69
|
637 int32_t getBestSuppIndex(LSR desiredLSR, LocaleLsrIterator *remainingIter, UErrorCode &errorCode) const;
|
jpayne@69
|
638
|
jpayne@69
|
639 const XLikelySubtags &likelySubtags;
|
jpayne@69
|
640 const LocaleDistance &localeDistance;
|
jpayne@69
|
641 int32_t thresholdDistance;
|
jpayne@69
|
642 int32_t demotionPerDesiredLocale;
|
jpayne@69
|
643 ULocMatchFavorSubtag favorSubtag;
|
jpayne@69
|
644 ULocMatchDirection direction;
|
jpayne@69
|
645
|
jpayne@69
|
646 // These are in input order.
|
jpayne@69
|
647 const Locale ** supportedLocales;
|
jpayne@69
|
648 LSR *lsrs;
|
jpayne@69
|
649 int32_t supportedLocalesLength;
|
jpayne@69
|
650 // These are in preference order: 1. Default locale 2. paradigm locales 3. others.
|
jpayne@69
|
651 UHashtable *supportedLsrToIndex; // Map<LSR, Integer> stores index+1 because 0 is "not found"
|
jpayne@69
|
652 // Array versions of the supportedLsrToIndex keys and values.
|
jpayne@69
|
653 // The distance lookup loops over the supportedLSRs and returns the index of the best match.
|
jpayne@69
|
654 const LSR **supportedLSRs;
|
jpayne@69
|
655 int32_t *supportedIndexes;
|
jpayne@69
|
656 int32_t supportedLSRsLength;
|
jpayne@69
|
657 Locale *ownedDefaultLocale;
|
jpayne@69
|
658 const Locale *defaultLocale;
|
jpayne@69
|
659 };
|
jpayne@69
|
660
|
jpayne@69
|
661 U_NAMESPACE_END
|
jpayne@69
|
662
|
jpayne@69
|
663 #endif // U_FORCE_HIDE_DRAFT_API
|
jpayne@69
|
664 #endif // U_SHOW_CPLUSPLUS_API
|
jpayne@69
|
665 #endif // __LOCALEMATCHER_H__
|