-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathlocalehelper.cpp
140 lines (126 loc) · 4.66 KB
/
localehelper.cpp
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
#include "./localehelper.h"
#include <c++utilities/conversion/stringconversion.h>
#include <unordered_map>
using namespace std::literals;
namespace TagParser {
/// \cond
static const auto &languageNames_ISO_639_2_b()
{
#include "resources/iso_language_codes.h"
return languageNames_iso_639_2_b;
}
/// \endcond
/*!
* \brief Returns whether an ISO-639-2 \a languageSpecification is not empty or undefined.
*/
inline static bool isLanguageDefined_ISO_639_2(const std::string &languageSpecification)
{
return !languageSpecification.empty() && languageSpecification != "und" && languageSpecification != "XXX";
}
/*!
* \brief Returns the language name for the specified ISO-639-2 code (bibliographic, 639-2/B).
* \remarks If \a isoCode is unknown an empty string is returned.
*/
static const std::string &languageName_ISO_639_2(const std::string &isoCode)
{
static const std::string empty;
if (!isLanguageDefined_ISO_639_2(isoCode)) {
return empty;
}
const auto &mapping = languageNames_ISO_639_2_b();
const auto i = mapping.find(isoCode);
if (i == mapping.cend()) {
return empty;
}
return i->second;
}
/*!
* \brief Returns an empty LocaleDetail.
*/
const LocaleDetail &LocaleDetail::getEmpty()
{
static const auto empty = LocaleDetail();
return empty;
}
/*!
* \brief Returns the abbreviated name of the specified \a format.
*
* This function returns the \a format if present. Otherwise it returns an empty string. This might be
* improved in the future, e.g. to convert to the specified \a format. It would also be possible to combine
* multiple details. For instance, if BCP-47 is required but only an ISO language and a domain name country
* are present, both could be combined and returned as BCP-47 abbreviation.
*/
const LocaleDetail &Locale::abbreviatedName(LocaleFormat format) const
{
for (const auto &detail : *this) {
if (!detail.empty() && detail.format == format && isLanguageDefined_ISO_639_2(detail)) {
return detail;
}
}
return LocaleDetail::getEmpty();
}
/*!
* \brief Returns *some* abbreviated name, *preferably* of the specified \a preferredFormat.
*
* This function returns the \a preferredFormat if present. Otherwise it returns the most relevant
* detail. This might be improved in the future, e.g. to convert to the \a preferredFormat. It would
* also be possible to combine multiple details. For instance, if BCP-47 is preferred but only an ISO
* language and a domain name country are present, both could be combined and returned as BCP-47 abbreviation.
*
* Returns an empty string if no details are present.
*
* \remarks This function is intended to be used for display purposes when the exact format doesn't matter and
* you just want to show the "best" abbreviation specified within the file.
*/
const LocaleDetail &Locale::someAbbreviatedName(LocaleFormat preferredFormat) const
{
auto format = LocaleFormat::Unknown;
const LocaleDetail *mostRelevantDetail = nullptr;
for (const auto &detail : *this) {
if (!detail.empty()
&& static_cast<std::underlying_type_t<LocaleFormat>>(detail.format) >= static_cast<std::underlying_type_t<LocaleFormat>>(format)) {
if (detail.format == preferredFormat) {
return detail;
}
format = detail.format;
mostRelevantDetail = &detail;
}
}
if (!mostRelevantDetail || !isLanguageDefined_ISO_639_2(*mostRelevantDetail)) {
return LocaleDetail::getEmpty();
}
return *mostRelevantDetail;
}
/*!
* \brief Returns the full name of the locale, e.g. Germany for the ISO code "ger" or an empty string if the
* full name is not known.
* \remarks So far the full name is only known for ISO-639-2/B codes.
*/
const std::string &TagParser::Locale::fullName() const
{
for (const auto &detail : *this) {
if (detail.format == LocaleFormat::ISO_639_2_B || detail.format == LocaleFormat::ISO_639_2_T) {
return languageName_ISO_639_2(detail);
}
}
return LocaleDetail::getEmpty();
}
/*!
* \brief Returns the full name if possible and otherwise falls back to the abbreviated name.
* \remarks This function is intended to be used for display purposes.
*/
const std::string &Locale::fullOrSomeAbbreviatedName() const
{
if (const auto &name = fullName(); !name.empty()) {
return name;
}
return someAbbreviatedName();
}
/*!
* \brief Returns all details as comma-separated string.
*/
std::string Locale::toString() const
{
return CppUtilities::joinStrings<std::vector<LocaleDetail>, std::string>(*this, LocaleDetail(", "sv, LocaleFormat::Unknown), true);
}
} // namespace TagParser