зеркало из https://github.com/mozilla/gecko-dev.git
158 строки
3.5 KiB
C++
158 строки
3.5 KiB
C++
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||
|
/* 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/. */
|
||
|
|
||
|
#include "mozilla/intl/MozLocale.h"
|
||
|
|
||
|
#include "unicode/uloc.h"
|
||
|
|
||
|
using namespace mozilla::intl;
|
||
|
|
||
|
/**
|
||
|
* Note: The file name is `MozLocale` to avoid compilation problems on case-insensitive
|
||
|
* Windows. The class name is `Locale`.
|
||
|
*/
|
||
|
Locale::Locale(const nsCString& aLocale, bool aRange)
|
||
|
: mLocaleStr(aLocale)
|
||
|
{
|
||
|
int32_t partNum = 0;
|
||
|
|
||
|
nsAutoCString normLocale(aLocale);
|
||
|
normLocale.ReplaceChar('_', '-');
|
||
|
|
||
|
for (const nsACString& part : normLocale.Split('-')) {
|
||
|
switch (partNum) {
|
||
|
case 0:
|
||
|
if (part.EqualsLiteral("*") ||
|
||
|
part.Length() == 2 || part.Length() == 3) {
|
||
|
mLanguage.Assign(part);
|
||
|
}
|
||
|
break;
|
||
|
case 1:
|
||
|
if (part.EqualsLiteral("*") || part.Length() == 4) {
|
||
|
mScript.Assign(part);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// fallover to region case
|
||
|
partNum++;
|
||
|
MOZ_FALLTHROUGH;
|
||
|
case 2:
|
||
|
if (part.EqualsLiteral("*") || part.Length() == 2) {
|
||
|
mRegion.Assign(part);
|
||
|
}
|
||
|
break;
|
||
|
case 3:
|
||
|
if (part.EqualsLiteral("*") || (part.Length() >= 3 && part.Length() <= 8)) {
|
||
|
mVariant.Assign(part);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
partNum++;
|
||
|
}
|
||
|
|
||
|
if (aRange) {
|
||
|
if (mLanguage.IsEmpty()) {
|
||
|
mLanguage.AssignLiteral("*");
|
||
|
}
|
||
|
if (mScript.IsEmpty()) {
|
||
|
mScript.AssignLiteral("*");
|
||
|
}
|
||
|
if (mRegion.IsEmpty()) {
|
||
|
mRegion.AssignLiteral("*");
|
||
|
}
|
||
|
if (mVariant.IsEmpty()) {
|
||
|
mVariant.AssignLiteral("*");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static bool
|
||
|
SubtagMatches(const nsCString& aSubtag1, const nsCString& aSubtag2)
|
||
|
{
|
||
|
return aSubtag1.EqualsLiteral("*") ||
|
||
|
aSubtag2.EqualsLiteral("*") ||
|
||
|
aSubtag1.Equals(aSubtag2, nsCaseInsensitiveCStringComparator());
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
Locale::Matches(const Locale& aLocale) const
|
||
|
{
|
||
|
return SubtagMatches(mLanguage, aLocale.mLanguage) &&
|
||
|
SubtagMatches(mScript, aLocale.mScript) &&
|
||
|
SubtagMatches(mRegion, aLocale.mRegion) &&
|
||
|
SubtagMatches(mVariant, aLocale.mVariant);
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
Locale::LanguageMatches(const Locale& aLocale) const
|
||
|
{
|
||
|
return SubtagMatches(mLanguage, aLocale.mLanguage) &&
|
||
|
SubtagMatches(mScript, aLocale.mScript);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
Locale::SetVariantRange()
|
||
|
{
|
||
|
mVariant.AssignLiteral("*");
|
||
|
}
|
||
|
|
||
|
void
|
||
|
Locale::SetRegionRange()
|
||
|
{
|
||
|
mRegion.AssignLiteral("*");
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
Locale::AddLikelySubtags()
|
||
|
{
|
||
|
return AddLikelySubtagsForLocale(mLocaleStr);
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
Locale::AddLikelySubtagsWithoutRegion()
|
||
|
{
|
||
|
nsAutoCString locale(mLanguage);
|
||
|
|
||
|
if (!mScript.IsEmpty()) {
|
||
|
locale.Append("-");
|
||
|
locale.Append(mScript);
|
||
|
}
|
||
|
|
||
|
// We don't add variant here because likelySubtag doesn't care about it.
|
||
|
|
||
|
return AddLikelySubtagsForLocale(locale);
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
Locale::AddLikelySubtagsForLocale(const nsACString& aLocale)
|
||
|
{
|
||
|
const int32_t kLocaleMax = 160;
|
||
|
char maxLocale[kLocaleMax];
|
||
|
nsAutoCString locale(aLocale);
|
||
|
|
||
|
UErrorCode status = U_ZERO_ERROR;
|
||
|
uloc_addLikelySubtags(locale.get(), maxLocale, kLocaleMax, &status);
|
||
|
|
||
|
if (U_FAILURE(status)) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
nsDependentCString maxLocStr(maxLocale);
|
||
|
Locale loc = Locale(maxLocStr, false);
|
||
|
|
||
|
if (loc == *this) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
mLanguage = loc.mLanguage;
|
||
|
mScript = loc.mScript;
|
||
|
mRegion = loc.mRegion;
|
||
|
|
||
|
// We don't update variant from likelySubtag since it's not going to
|
||
|
// provide it and we want to preserve the range
|
||
|
|
||
|
return true;
|
||
|
}
|