Bug 1428530 - Separate out mozilla::intl::Locale. r?jfkthame
MozReview-Commit-ID: IELFjNCoJEo
--- a/intl/locale/LocaleService.cpp
+++ b/intl/locale/LocaleService.cpp
@@ -5,16 +5,17 @@
#include "LocaleService.h"
#include <algorithm> // find_if()
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/Omnijar.h"
#include "mozilla/Preferences.h"
#include "mozilla/Services.h"
+#include "mozilla/intl/MozLocale.h"
#include "mozilla/intl/OSPreferences.h"
#include "nsIObserverService.h"
#include "nsIToolkitChromeRegistry.h"
#include "nsStringEnumerator.h"
#include "nsXULAppAPI.h"
#include "nsZipArchive.h"
#include "unicode/uloc.h"
@@ -799,159 +800,16 @@ LocaleService::NegotiateLanguages(const
*aCount = 0;
for (const auto& supported : supportedLocales) {
(*aRetVal)[(*aCount)++] = moz_xstrdup(supported.get());
}
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)
{
AutoTArray<nsCString, 16> requestedLocales;
bool res = GetRequestedLocales(requestedLocales);
if (!res) {
NS_ERROR("Couldn't retrieve selected locales from prefs!");
--- a/intl/locale/LocaleService.h
+++ b/intl/locale/LocaleService.h
@@ -248,60 +248,16 @@ public:
bool IsAppLocaleRTL();
static bool LanguagesMatch(const nsCString& aRequested,
const nsCString& aAvailable);
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,
nsTArray<nsCString>& aRetVal);
void NegotiateAppLocales(nsTArray<nsCString>& aRetVal);
virtual ~LocaleService();
new file mode 100644
--- /dev/null
+++ b/intl/locale/MozLocale.cpp
@@ -0,0 +1,157 @@
+/* -*- 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;
+}
new file mode 100644
--- /dev/null
+++ b/intl/locale/MozLocale.h
@@ -0,0 +1,64 @@
+/* -*- 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_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 "*".
+ *
+ * Note: The file name is `MozLocale` to avoid compilation problems on case-insensitive
+ * Windows. The class name is `Locale`.
+ */
+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__ */
--- a/intl/locale/moz.build
+++ b/intl/locale/moz.build
@@ -29,22 +29,24 @@ EXPORTS += [
'DateTimeFormat.h',
'nsCollationCID.h',
'nsLanguageAtomService.h',
'nsUConvPropertySearch.h',
]
EXPORTS.mozilla.intl += [
'LocaleService.h',
+ 'MozLocale.h',
'OSPreferences.h',
]
UNIFIED_SOURCES += [
'DateTimeFormat.cpp',
'LocaleService.cpp',
+ 'MozLocale.cpp',
'nsCollation.cpp',
'nsCollationFactory.cpp',
'nsLanguageAtomService.cpp',
'nsUConvPropertySearch.cpp',
'OSPreferences.cpp',
]
EXTRA_JS_MODULES += [