141 lines
4.7 KiB
C++
141 lines
4.7 KiB
C++
#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
|