mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-30 00:01:50 +00:00
Bug 1428530 - Separate out mozilla::intl::Locale. r=jfkthame
MozReview-Commit-ID: IELFjNCoJEo --HG-- extra : rebase_source : a735a893e93669af5b91951519ea9dadeb8123ad
This commit is contained in:
parent
aab6457784
commit
9ca3cdc5a5
153
intl/locale/Locale.cpp
Normal file
153
intl/locale/Locale.cpp
Normal file
@ -0,0 +1,153 @@
|
||||
/* -*- 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 "Locale.h"
|
||||
|
||||
#include "unicode/uloc.h"
|
||||
|
||||
using namespace mozilla::intl;
|
||||
|
||||
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;
|
||||
}
|
56
intl/locale/Locale.h
Normal file
56
intl/locale/Locale.h
Normal file
@ -0,0 +1,56 @@
|
||||
#ifndef mozilla_intl_Locale_h__
|
||||
#define mozilla_intl_Locale_h__
|
||||
|
||||
#include "nsString.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace intl {
|
||||
|
||||
/**
|
||||
* Locale object, a BCP47-style tag decomposed into subtags for
|
||||
* matching purposes.
|
||||
*
|
||||
* If constructed with aRange = true, any missing subtags will be
|
||||
* set to "*".
|
||||
*/
|
||||
class Locale {
|
||||
public:
|
||||
Locale(const nsCString& aLocale, bool aRange);
|
||||
|
||||
bool Matches(const Locale& aLocale) const;
|
||||
bool LanguageMatches(const Locale& aLocale) const;
|
||||
|
||||
|
||||
void SetVariantRange();
|
||||
void SetRegionRange();
|
||||
|
||||
// returns false if nothing changed
|
||||
bool AddLikelySubtags();
|
||||
bool AddLikelySubtagsWithoutRegion();
|
||||
|
||||
const nsCString& AsString() const {
|
||||
return mLocaleStr;
|
||||
}
|
||||
|
||||
bool operator== (const Locale& aOther) {
|
||||
const auto& cmp = nsCaseInsensitiveCStringComparator();
|
||||
return mLanguage.Equals(aOther.mLanguage, cmp) &&
|
||||
mScript.Equals(aOther.mScript, cmp) &&
|
||||
mRegion.Equals(aOther.mRegion, cmp) &&
|
||||
mVariant.Equals(aOther.mVariant, cmp);
|
||||
}
|
||||
|
||||
private:
|
||||
const nsCString& mLocaleStr;
|
||||
nsCString mLanguage;
|
||||
nsCString mScript;
|
||||
nsCString mRegion;
|
||||
nsCString mVariant;
|
||||
|
||||
bool AddLikelySubtagsForLocale(const nsACString& aLocale);
|
||||
};
|
||||
|
||||
} // intl
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_intl_Locale_h__ */
|
@ -10,6 +10,7 @@
|
||||
#include "mozilla/Omnijar.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/intl/Locale.h"
|
||||
#include "mozilla/intl/OSPreferences.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIToolkitChromeRegistry.h"
|
||||
@ -804,149 +805,6 @@ LocaleService::NegotiateLanguages(const char** aRequested,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
LocaleService::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
|
||||
LocaleService::Locale::Matches(const LocaleService::Locale& aLocale) const
|
||||
{
|
||||
return SubtagMatches(mLanguage, aLocale.mLanguage) &&
|
||||
SubtagMatches(mScript, aLocale.mScript) &&
|
||||
SubtagMatches(mRegion, aLocale.mRegion) &&
|
||||
SubtagMatches(mVariant, aLocale.mVariant);
|
||||
}
|
||||
|
||||
bool
|
||||
LocaleService::Locale::LanguageMatches(const LocaleService::Locale& aLocale) const
|
||||
{
|
||||
return SubtagMatches(mLanguage, aLocale.mLanguage) &&
|
||||
SubtagMatches(mScript, aLocale.mScript);
|
||||
}
|
||||
|
||||
void
|
||||
LocaleService::Locale::SetVariantRange()
|
||||
{
|
||||
mVariant.AssignLiteral("*");
|
||||
}
|
||||
|
||||
void
|
||||
LocaleService::Locale::SetRegionRange()
|
||||
{
|
||||
mRegion.AssignLiteral("*");
|
||||
}
|
||||
|
||||
bool
|
||||
LocaleService::Locale::AddLikelySubtags()
|
||||
{
|
||||
return AddLikelySubtagsForLocale(mLocaleStr);
|
||||
}
|
||||
|
||||
bool
|
||||
LocaleService::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
|
||||
LocaleService::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;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
LocaleService::GetRequestedLocales(uint32_t* aCount, char*** aOutArray)
|
||||
{
|
||||
|
@ -253,50 +253,6 @@ public:
|
||||
bool IsServer();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Locale object, a BCP47-style tag decomposed into subtags for
|
||||
* matching purposes.
|
||||
*
|
||||
* If constructed with aRange = true, any missing subtags will be
|
||||
* set to "*".
|
||||
*/
|
||||
class Locale
|
||||
{
|
||||
public:
|
||||
Locale(const nsCString& aLocale, bool aRange);
|
||||
|
||||
bool Matches(const Locale& aLocale) const;
|
||||
bool LanguageMatches(const Locale& aLocale) const;
|
||||
|
||||
void SetVariantRange();
|
||||
void SetRegionRange();
|
||||
|
||||
// returns false if nothing changed
|
||||
bool AddLikelySubtags();
|
||||
bool AddLikelySubtagsWithoutRegion();
|
||||
|
||||
const nsCString& AsString() const {
|
||||
return mLocaleStr;
|
||||
}
|
||||
|
||||
bool operator== (const Locale& aOther) {
|
||||
const auto& cmp = nsCaseInsensitiveCStringComparator();
|
||||
return mLanguage.Equals(aOther.mLanguage, cmp) &&
|
||||
mScript.Equals(aOther.mScript, cmp) &&
|
||||
mRegion.Equals(aOther.mRegion, cmp) &&
|
||||
mVariant.Equals(aOther.mVariant, cmp);
|
||||
}
|
||||
|
||||
private:
|
||||
const nsCString& mLocaleStr;
|
||||
nsCString mLanguage;
|
||||
nsCString mScript;
|
||||
nsCString mRegion;
|
||||
nsCString mVariant;
|
||||
|
||||
bool AddLikelySubtagsForLocale(const nsACString& aLocale);
|
||||
};
|
||||
|
||||
void FilterMatches(const nsTArray<nsCString>& aRequested,
|
||||
const nsTArray<nsCString>& aAvailable,
|
||||
LangNegStrategy aStrategy,
|
||||
|
@ -33,12 +33,14 @@ EXPORTS += [
|
||||
]
|
||||
|
||||
EXPORTS.mozilla.intl += [
|
||||
'Locale.h',
|
||||
'LocaleService.h',
|
||||
'OSPreferences.h',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'DateTimeFormat.cpp',
|
||||
'Locale.cpp',
|
||||
'LocaleService.cpp',
|
||||
'nsCollation.cpp',
|
||||
'nsCollationFactory.cpp',
|
||||
|
Loading…
Reference in New Issue
Block a user