forked from mozilla/gecko-dev
-
Notifications
You must be signed in to change notification settings - Fork 1
/
MozLocale.h
160 lines (140 loc) · 5.07 KB
/
MozLocale.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode:nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_intl_MozLocale_h__
#define mozilla_intl_MozLocale_h__
#include "nsString.h"
#include "nsTArray.h"
#include "MozLocaleBindings.h"
namespace mozilla {
namespace intl {
/**
* Locale class is a core representation of a single locale.
*
* A locale is a data object representing a combination of language, script,
* region, variant and a set of regional extension preferences that may further
* specify particular user choices like calendar, numbering system, etc.
*
* A locale can be expressed as a language tag string, like a simple "fr" for
* French, or a more specific "sr-Cyrl-RS-u-hc-h12" for Serbian in Russia with a
* Cyrylic script, and hour cycle selected to be `h12`.
*
* The format of the language tag follows BCP47 standard and implements a subset
* of it. In the future we expect to extend this class to cover more subtags and
* extensions.
*
* BCP47: https://tools.ietf.org/html/bcp47
*
* The aim of this class it aid in validation, parsing and canonicalization of
* the string.
*
* It allows the user to input any well-formed BCP47 language tag and operate
* on its subtags in a canonicalized form.
*
* It should be used for all operations on language tags, and together with
* LocaleService::NegotiateLanguages for language negotiation.
*
* Example:
*
* MozLocale loc = MozLocale("de-at");
*
* ASSERT_TRUE(loc.GetLanguage().Equals("de"));
* ASSERT_TRUE(loc.GetScript().IsEmpty());
* ASSERT_TRUE(loc.GetRegion().Equals("AT")); // canonicalized to upper case
*/
class MozLocale {
public:
/**
* The constructor expects the input to be a well-formed BCP47-style locale
* string.
*
* Two operations are performed on the well-formed language tags:
*
* * Case normalization to conform with BCP47 (e.g. "eN-uS" -> "en-US")
* * Underscore delimiters replaced with dashed (e.g. "en_US" -> "en-US")
*
* If the input language tag string is not well-formed, the Locale will be
* created with its flag `mWellFormed` set to false which will make the Locale
* never match.
*/
explicit MozLocale(const nsACString& aLocale);
explicit MozLocale(const char* aLocale)
: MozLocale(nsDependentCString(aLocale)){};
const nsDependentCSubstring GetLanguage() const;
const nsDependentCSubstring GetScript() const;
const nsDependentCSubstring GetRegion() const;
void GetVariants(nsTArray<nsCString>& aRetVal) const;
/**
* Returns a `true` if the locale is well-formed, such that the
* Locale object can validly be matched against others.
*/
bool IsWellFormed() const { return mIsWellFormed; }
/**
* Returns a canonicalized language tag string of the locale.
*/
const nsCString AsString() const;
/**
* Compares two locales optionally treating one or both of
* the locales as a range.
*
* In case one of the locales is treated as a range, its
* empty fields are considered to match all possible
* values of the same field on the other locale.
*
* Example:
*
* Locale("en").Matches(Locale("en-US"), false, false) // false
* Locale("en").Matches(Locale("en-US"), true, false) // true
*
* The latter returns true because the region field on the "en"
* locale is being treated as a range and matches any region field
* value including "US" of the other locale.
*/
bool Matches(const MozLocale& aOther, bool aThisRange,
bool aOtherRange) const;
/**
* This operation uses CLDR data to build a more specific version
* of a generic locale.
*
* Example:
*
* Locale("en").Maximize().AsString(); // "en-Latn-US"
*/
bool Maximize();
/**
* Clears the variants field of the Locale object.
*/
void ClearVariants();
/**
* Clears the region field of the Locale object.
*/
void ClearRegion();
/**
* Marks the locale as invalid which in turns makes
* it to be skipped by most LocaleService operations.
*/
void Invalidate() { mIsWellFormed = false; }
/**
* Compares two locales expecting all fields to match each other.
*/
bool operator==(const MozLocale& aOther) {
// Note: non-well-formed Locale objects are never
// treated as equal to anything
// (even other non-well-formed ones).
return Matches(aOther, false, false);
}
MozLocale(MozLocale&& aOther)
: mIsWellFormed(aOther.mIsWellFormed), mRaw(std::move(aOther.mRaw)) {}
ffi::LanguageIdentifier* Raw() { return mRaw.get(); }
const ffi::LanguageIdentifier* Raw() const { return mRaw.get(); }
private:
bool mIsWellFormed;
// Notice. We had to remove `const` to allow for move constructor, but
// that makes it possible to nullptr `mRaw`. Just don't.
UniquePtr<ffi::LanguageIdentifier> mRaw;
};
} // namespace intl
} // namespace mozilla
MOZ_DECLARE_RELOCATE_USING_MOVE_CONSTRUCTOR(mozilla::intl::MozLocale)
#endif /* mozilla_intl_MozLocale_h__ */