зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 9 changesets (bug 1736017) for causing bustages in nsLineBreaker.cpp
Backed out changeset d7b7427bb29e (bug 1736017) Backed out changeset 7249dec70600 (bug 1736017) Backed out changeset f16572806b0c (bug 1736017) Backed out changeset a78125c71b3e (bug 1736017) Backed out changeset 84ba2cbd596a (bug 1736017) Backed out changeset f771265e0930 (bug 1736017) Backed out changeset c0cef271022d (bug 1736017) Backed out changeset 19be73147fcc (bug 1736017) Backed out changeset 11721cc861b0 (bug 1736017)
This commit is contained in:
Родитель
c27561cbb3
Коммит
25dd04d4c5
|
@ -12,12 +12,11 @@
|
|||
#include "mozilla/AutoRestore.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/intl/LineBreaker.h"
|
||||
#include "mozilla/intl/Locale.h"
|
||||
#include "mozilla/intl/MozLocale.h"
|
||||
|
||||
using mozilla::AutoRestore;
|
||||
using mozilla::intl::LineBreaker;
|
||||
using mozilla::intl::Locale;
|
||||
using mozilla::intl::LocaleParser;
|
||||
using mozilla::intl::MozLocale;
|
||||
|
||||
nsLineBreaker::nsLineBreaker()
|
||||
: mCurrentWordLanguage(nullptr),
|
||||
|
@ -472,16 +471,14 @@ void nsLineBreaker::UpdateCurrentWordLanguage(nsAtom* aHyphenationLanguage) {
|
|||
mScriptIsChineseOrJapanese = false;
|
||||
} else {
|
||||
if (aHyphenationLanguage && !mCurrentWordLanguage) {
|
||||
Locale loc;
|
||||
auto result =
|
||||
LocaleParser::tryParse(nsAtomCString(aHyphenationLanguage), loc);
|
||||
if (result.isOk() && loc.script().missing()) {
|
||||
if (loc.addLikelySubtags()) {
|
||||
mScriptIsChineseOrJapanese =
|
||||
loc.script().equalTo("Hans") || loc.script().equalTo("Hant") ||
|
||||
loc.script().equalTo("Jpan") || loc.script().equalTo("Hrkt");
|
||||
}
|
||||
MozLocale loc = MozLocale(nsAtomCString(aHyphenationLanguage));
|
||||
if (loc.GetScript().IsEmpty()) {
|
||||
loc.Maximize();
|
||||
}
|
||||
const nsDependentCSubstring& script = loc.GetScript();
|
||||
mScriptIsChineseOrJapanese =
|
||||
script.EqualsLiteral("Hans") || script.EqualsLiteral("Hant") ||
|
||||
script.EqualsLiteral("Jpan") || script.EqualsLiteral("Hrkt");
|
||||
}
|
||||
mCurrentWordLanguage = aHyphenationLanguage;
|
||||
}
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
#include "mozilla/dom/RootedDictionary.h"
|
||||
#include "mozilla/dom/UserActivation.h"
|
||||
#include "mozilla/dom/WindowContext.h"
|
||||
#include "mozilla/intl/Locale.h"
|
||||
#include "mozilla/intl/LocaleService.h"
|
||||
#include "mozilla/intl/MozLocale.h"
|
||||
#include "mozilla/StaticPrefs_dom.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIDUtils.h"
|
||||
|
@ -95,10 +95,8 @@ bool PaymentRequest::PrefEnabled(JSContext* aCx, JSObject* aObj) {
|
|||
}
|
||||
nsAutoCString locale;
|
||||
LocaleService::GetInstance()->GetAppLocaleAsBCP47(locale);
|
||||
mozilla::intl::Locale loc;
|
||||
auto result = mozilla::intl::LocaleParser::tryParse(locale, loc);
|
||||
if (!(result.isOk() && loc.language().equalTo("en") &&
|
||||
loc.region().equalTo("US"))) {
|
||||
mozilla::intl::MozLocale loc = mozilla::intl::MozLocale(locale);
|
||||
if (!(loc.GetLanguage() == "en" && loc.GetRegion() == "US")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/Selection.h"
|
||||
#include "mozilla/dom/StaticRange.h"
|
||||
#include "mozilla/intl/Locale.h" // for mozilla::intl::Locale
|
||||
#include "mozilla/intl/LocaleService.h" // for retrieving app locale
|
||||
#include "mozilla/intl/MozLocale.h" // for mozilla::intl::Locale
|
||||
#include "mozilla/intl/OSPreferences.h" // for mozilla::intl::OSPreferences
|
||||
#include "mozilla/Logging.h" // for mozilla::LazyLogModule
|
||||
#include "mozilla/mozalloc.h" // for operator delete, etc
|
||||
|
@ -893,66 +893,58 @@ void EditorSpellCheck::SetFallbackDictionary(DictionaryFetcher* aFetcher) {
|
|||
|
||||
// Required dictionary was not available. Try to get a dictionary
|
||||
// matching at least language part of dictName.
|
||||
mozilla::intl::Locale loc;
|
||||
if (mozilla::intl::LocaleParser::tryParse(dictName, loc).isOk()) {
|
||||
Span<const char> language = loc.language().span();
|
||||
nsAutoCString langCode(language.data(), language.size());
|
||||
mozilla::intl::MozLocale loc = mozilla::intl::MozLocale(dictName);
|
||||
nsAutoCString langCode(loc.GetLanguage());
|
||||
|
||||
// Try dictionary.spellchecker preference, if it starts with langCode,
|
||||
// so we don't just get any random dictionary matching the language.
|
||||
if (!preferredDict.IsEmpty() &&
|
||||
nsStyleUtil::DashMatchCompare(NS_ConvertUTF8toUTF16(preferredDict),
|
||||
NS_ConvertUTF8toUTF16(langCode),
|
||||
nsTDefaultStringComparator)) {
|
||||
// Try dictionary.spellchecker preference, if it starts with langCode,
|
||||
// so we don't just get any random dictionary matching the language.
|
||||
if (!preferredDict.IsEmpty() &&
|
||||
nsStyleUtil::DashMatchCompare(NS_ConvertUTF8toUTF16(preferredDict),
|
||||
NS_ConvertUTF8toUTF16(langCode),
|
||||
nsTDefaultStringComparator)) {
|
||||
#ifdef DEBUG_DICT
|
||||
printf(
|
||||
"***** Trying preference value |%s| since it matches language "
|
||||
"code\n",
|
||||
preferredDict.get());
|
||||
printf(
|
||||
"***** Trying preference value |%s| since it matches language code\n",
|
||||
preferredDict.get());
|
||||
#endif
|
||||
BuildDictionaryList(preferredDict, dictList,
|
||||
DICT_COMPARE_CASE_INSENSITIVE, tryDictList);
|
||||
}
|
||||
|
||||
if (tryDictList.IsEmpty()) {
|
||||
// Use the application locale dictionary when the required language
|
||||
// equlas applocation locale language.
|
||||
LocaleService::GetInstance()->GetAppLocaleAsBCP47(appLocaleStr);
|
||||
if (!appLocaleStr.IsEmpty()) {
|
||||
mozilla::intl::Locale appLoc;
|
||||
auto result =
|
||||
mozilla::intl::LocaleParser::tryParse(appLocaleStr, appLoc);
|
||||
if (result.isOk() &&
|
||||
loc.language().span() == appLoc.language().span()) {
|
||||
BuildDictionaryList(appLocaleStr, dictList,
|
||||
DICT_COMPARE_CASE_INSENSITIVE, tryDictList);
|
||||
}
|
||||
}
|
||||
|
||||
// Use the system locale dictionary when the required language equlas
|
||||
// system locale language.
|
||||
nsAutoCString sysLocaleStr;
|
||||
OSPreferences::GetInstance()->GetSystemLocale(sysLocaleStr);
|
||||
if (!sysLocaleStr.IsEmpty()) {
|
||||
mozilla::intl::Locale sysLoc;
|
||||
auto result =
|
||||
mozilla::intl::LocaleParser::tryParse(sysLocaleStr, sysLoc);
|
||||
if (result.isOk() &&
|
||||
loc.language().span() == sysLoc.language().span()) {
|
||||
BuildDictionaryList(sysLocaleStr, dictList,
|
||||
DICT_COMPARE_CASE_INSENSITIVE, tryDictList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Use any dictionary with the required language.
|
||||
#ifdef DEBUG_DICT
|
||||
printf("***** Trying to find match for language code |%s|\n",
|
||||
langCode.get());
|
||||
#endif
|
||||
BuildDictionaryList(langCode, dictList, DICT_COMPARE_DASHMATCH,
|
||||
tryDictList);
|
||||
BuildDictionaryList(preferredDict, dictList,
|
||||
DICT_COMPARE_CASE_INSENSITIVE, tryDictList);
|
||||
}
|
||||
|
||||
if (tryDictList.IsEmpty()) {
|
||||
// Use the application locale dictionary when the required language
|
||||
// equlas applocation locale language.
|
||||
LocaleService::GetInstance()->GetAppLocaleAsBCP47(appLocaleStr);
|
||||
if (!appLocaleStr.IsEmpty()) {
|
||||
mozilla::intl::MozLocale appLoc =
|
||||
mozilla::intl::MozLocale(appLocaleStr);
|
||||
if (langCode.Equals(appLoc.GetLanguage())) {
|
||||
BuildDictionaryList(appLocaleStr, dictList,
|
||||
DICT_COMPARE_CASE_INSENSITIVE, tryDictList);
|
||||
}
|
||||
}
|
||||
|
||||
// Use the system locale dictionary when the required language equlas
|
||||
// system locale language.
|
||||
nsAutoCString sysLocaleStr;
|
||||
OSPreferences::GetInstance()->GetSystemLocale(sysLocaleStr);
|
||||
if (!sysLocaleStr.IsEmpty()) {
|
||||
mozilla::intl::MozLocale sysLoc =
|
||||
mozilla::intl::MozLocale(sysLocaleStr);
|
||||
if (langCode.Equals(sysLoc.GetLanguage())) {
|
||||
BuildDictionaryList(sysLocaleStr, dictList,
|
||||
DICT_COMPARE_CASE_INSENSITIVE, tryDictList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Use any dictionary with the required language.
|
||||
#ifdef DEBUG_DICT
|
||||
printf("***** Trying to find match for language code |%s|\n",
|
||||
langCode.get());
|
||||
#endif
|
||||
BuildDictionaryList(langCode, dictList, DICT_COMPARE_DASHMATCH,
|
||||
tryDictList);
|
||||
}
|
||||
|
||||
// Priority 3:
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
|
||||
#include "mozilla/Logging.h"
|
||||
#include "mozilla/gfx/Logging.h"
|
||||
#include "mozilla/intl/Locale.h"
|
||||
#include "mozilla/intl/LocaleService.h"
|
||||
#include "mozilla/intl/MozLocale.h"
|
||||
#include "mozilla/intl/OSPreferences.h"
|
||||
|
||||
#include "gfxPlatformFontList.h"
|
||||
|
@ -50,9 +50,8 @@
|
|||
#include <numeric>
|
||||
|
||||
using namespace mozilla;
|
||||
using mozilla::intl::Locale;
|
||||
using mozilla::intl::LocaleParser;
|
||||
using mozilla::intl::LocaleService;
|
||||
using mozilla::intl::MozLocale;
|
||||
using mozilla::intl::OSPreferences;
|
||||
|
||||
#define LOG_FONTLIST(args) \
|
||||
|
@ -2172,21 +2171,19 @@ void gfxPlatformFontList::AppendCJKPrefLangs(eFontPrefLang aPrefLangs[],
|
|||
LocaleService::GetInstance()->GetAppLocaleAsBCP47(localeStr);
|
||||
|
||||
{
|
||||
Locale locale;
|
||||
if (LocaleParser::tryParse(localeStr, locale).isOk()) {
|
||||
if (locale.language().equalTo("ja")) {
|
||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Japanese);
|
||||
} else if (locale.language().equalTo("zh")) {
|
||||
if (locale.region().equalTo("CN")) {
|
||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseCN);
|
||||
} else if (locale.region().equalTo("TW")) {
|
||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseTW);
|
||||
} else if (locale.region().equalTo("HK")) {
|
||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseHK);
|
||||
}
|
||||
} else if (locale.language().equalTo("ko")) {
|
||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Korean);
|
||||
MozLocale locale(localeStr);
|
||||
if (locale.GetLanguage().Equals("ja")) {
|
||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Japanese);
|
||||
} else if (locale.GetLanguage().Equals("zh")) {
|
||||
if (locale.GetRegion().Equals("CN")) {
|
||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseCN);
|
||||
} else if (locale.GetRegion().Equals("TW")) {
|
||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseTW);
|
||||
} else if (locale.GetRegion().Equals("HK")) {
|
||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseHK);
|
||||
}
|
||||
} else if (locale.GetLanguage().Equals("ko")) {
|
||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Korean);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2206,22 +2203,20 @@ void gfxPlatformFontList::AppendCJKPrefLangs(eFontPrefLang aPrefLangs[],
|
|||
sysLocales, prefLocales, ""_ns,
|
||||
LocaleService::kLangNegStrategyFiltering, negLocales);
|
||||
for (const auto& localeStr : negLocales) {
|
||||
Locale locale;
|
||||
if (auto result = LocaleParser::tryParse(localeStr, locale);
|
||||
result.isOk()) {
|
||||
if (locale.language().equalTo("ja")) {
|
||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Japanese);
|
||||
} else if (locale.language().equalTo("zh")) {
|
||||
if (locale.region().equalTo("CN")) {
|
||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseCN);
|
||||
} else if (locale.region().equalTo("TW")) {
|
||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseTW);
|
||||
} else if (locale.region().equalTo("HK")) {
|
||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseHK);
|
||||
}
|
||||
} else if (locale.language().equalTo("ko")) {
|
||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Korean);
|
||||
MozLocale locale(localeStr);
|
||||
|
||||
if (locale.GetLanguage().Equals("ja")) {
|
||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Japanese);
|
||||
} else if (locale.GetLanguage().Equals("zh")) {
|
||||
if (locale.GetRegion().Equals("CN")) {
|
||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseCN);
|
||||
} else if (locale.GetRegion().Equals("TW")) {
|
||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseTW);
|
||||
} else if (locale.GetRegion().Equals("HK")) {
|
||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_ChineseHK);
|
||||
}
|
||||
} else if (locale.GetLanguage().Equals("ko")) {
|
||||
AppendPrefLang(tempPrefLangs, tempLen, eFontPrefLang_Korean);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/StaticPrefs_privacy.h"
|
||||
#include "mozilla/intl/Locale.h"
|
||||
#include "mozilla/intl/MozLocale.h"
|
||||
#include "mozilla/intl/OSPreferences.h"
|
||||
#include "nsDirectoryService.h"
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
|
@ -303,16 +303,9 @@ LocaleService::Observe(nsISupports* aSubject, const char* aTopic,
|
|||
|
||||
bool LocaleService::LanguagesMatch(const nsACString& aRequested,
|
||||
const nsACString& aAvailable) {
|
||||
Locale requested;
|
||||
auto requestedResult = LocaleParser::tryParse(aRequested, requested);
|
||||
Locale available;
|
||||
auto availableResult = LocaleParser::tryParse(aAvailable, available);
|
||||
|
||||
if (requestedResult.isErr() || availableResult.isErr()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return requested.language().span() == available.language().span();
|
||||
MozLocale requested = MozLocale(aRequested);
|
||||
MozLocale available = MozLocale(aAvailable);
|
||||
return requested.GetLanguage().Equals(available.GetLanguage());
|
||||
}
|
||||
|
||||
bool LocaleService::IsServer() { return mIsServer; }
|
||||
|
@ -534,14 +527,9 @@ LocaleService::NegotiateLanguages(const nsTArray<nsCString>& aRequested,
|
|||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
Locale parsedLocale;
|
||||
auto result = LocaleParser::tryParse(aDefaultLocale, parsedLocale);
|
||||
|
||||
MOZ_ASSERT(
|
||||
aDefaultLocale.IsEmpty() || result.isOk(),
|
||||
aDefaultLocale.IsEmpty() || MozLocale(aDefaultLocale).IsWellFormed(),
|
||||
"If specified, default locale must be a well-formed BCP47 language tag.");
|
||||
#endif
|
||||
|
||||
if (aStrategy == kLangNegStrategyLookup && aDefaultLocale.IsEmpty()) {
|
||||
NS_WARNING(
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
/* -*- Mode: C++; tab-width: 4; 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/. */
|
||||
|
||||
#include "mozilla/intl/MozLocale.h"
|
||||
|
||||
using namespace mozilla::intl;
|
||||
using namespace mozilla::intl::ffi;
|
||||
|
||||
MozLocale::MozLocale(const nsACString& aLocale)
|
||||
: mRaw(unic_langid_new(&aLocale, &mIsWellFormed)) {}
|
||||
|
||||
const nsCString MozLocale::AsString() const {
|
||||
nsCString tag;
|
||||
unic_langid_as_string(mRaw.get(), &tag);
|
||||
return tag;
|
||||
}
|
||||
|
||||
const nsDependentCSubstring MozLocale::GetLanguage() const {
|
||||
nsDependentCSubstring sub;
|
||||
unic_langid_get_language(mRaw.get(), &sub);
|
||||
return sub;
|
||||
}
|
||||
|
||||
const nsDependentCSubstring MozLocale::GetScript() const {
|
||||
nsDependentCSubstring sub;
|
||||
unic_langid_get_script(mRaw.get(), &sub);
|
||||
return sub;
|
||||
}
|
||||
|
||||
const nsDependentCSubstring MozLocale::GetRegion() const {
|
||||
nsDependentCSubstring sub;
|
||||
unic_langid_get_region(mRaw.get(), &sub);
|
||||
return sub;
|
||||
}
|
||||
|
||||
void MozLocale::GetVariants(nsTArray<nsCString>& aRetVal) const {
|
||||
unic_langid_get_variants(mRaw.get(), &aRetVal);
|
||||
}
|
||||
|
||||
bool MozLocale::Matches(const MozLocale& aOther, bool aThisRange,
|
||||
bool aOtherRange) const {
|
||||
if (!IsWellFormed() || !aOther.IsWellFormed()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return unic_langid_matches(mRaw.get(), aOther.Raw(), aThisRange, aOtherRange);
|
||||
}
|
||||
|
||||
bool MozLocale::Maximize() { return unic_langid_maximize(mRaw.get()); }
|
||||
|
||||
void MozLocale::ClearVariants() { unic_langid_clear_variants(mRaw.get()); }
|
||||
|
||||
void MozLocale::ClearRegion() { unic_langid_clear_region(mRaw.get()); }
|
|
@ -0,0 +1,160 @@
|
|||
/* -*- 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_MozLocale_h__
|
||||
#define mozilla_intl_MozLocale_h__
|
||||
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
#include "MozLocaleBindings.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace intl {
|
||||
|
||||
/**
|
||||
* Locale class is a core representation of a single locale.
|
||||
*
|
||||
* A locale is a data object representing a combination of language, script,
|
||||
* region, variant and a set of regional extension preferences that may further
|
||||
* specify particular user choices like calendar, numbering system, etc.
|
||||
*
|
||||
* A locale can be expressed as a language tag string, like a simple "fr" for
|
||||
* French, or a more specific "sr-Cyrl-RS-u-hc-h12" for Serbian in Russia with a
|
||||
* Cyrylic script, and hour cycle selected to be `h12`.
|
||||
*
|
||||
* The format of the language tag follows BCP47 standard and implements a subset
|
||||
* of it. In the future we expect to extend this class to cover more subtags and
|
||||
* extensions.
|
||||
*
|
||||
* BCP47: https://tools.ietf.org/html/bcp47
|
||||
*
|
||||
* The aim of this class it aid in validation, parsing and canonicalization of
|
||||
* the string.
|
||||
*
|
||||
* It allows the user to input any well-formed BCP47 language tag and operate
|
||||
* on its subtags in a canonicalized form.
|
||||
*
|
||||
* It should be used for all operations on language tags, and together with
|
||||
* LocaleService::NegotiateLanguages for language negotiation.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* MozLocale loc = MozLocale("de-at");
|
||||
*
|
||||
* ASSERT_TRUE(loc.GetLanguage().Equals("de"));
|
||||
* ASSERT_TRUE(loc.GetScript().IsEmpty());
|
||||
* ASSERT_TRUE(loc.GetRegion().Equals("AT")); // canonicalized to upper case
|
||||
*/
|
||||
class MozLocale {
|
||||
public:
|
||||
/**
|
||||
* The constructor expects the input to be a well-formed BCP47-style locale
|
||||
* string.
|
||||
*
|
||||
* Two operations are performed on the well-formed language tags:
|
||||
*
|
||||
* * Case normalization to conform with BCP47 (e.g. "eN-uS" -> "en-US")
|
||||
* * Underscore delimiters replaced with dashed (e.g. "en_US" -> "en-US")
|
||||
*
|
||||
* If the input language tag string is not well-formed, the Locale will be
|
||||
* created with its flag `mWellFormed` set to false which will make the Locale
|
||||
* never match.
|
||||
*/
|
||||
explicit MozLocale(const nsACString& aLocale);
|
||||
explicit MozLocale(const char* aLocale)
|
||||
: MozLocale(nsDependentCString(aLocale)){};
|
||||
|
||||
const nsDependentCSubstring GetLanguage() const;
|
||||
const nsDependentCSubstring GetScript() const;
|
||||
const nsDependentCSubstring GetRegion() const;
|
||||
void GetVariants(nsTArray<nsCString>& aRetVal) const;
|
||||
|
||||
/**
|
||||
* Returns a `true` if the locale is well-formed, such that the
|
||||
* Locale object can validly be matched against others.
|
||||
*/
|
||||
bool IsWellFormed() const { return mIsWellFormed; }
|
||||
|
||||
/**
|
||||
* Returns a canonicalized language tag string of the locale.
|
||||
*/
|
||||
const nsCString AsString() const;
|
||||
|
||||
/**
|
||||
* Compares two locales optionally treating one or both of
|
||||
* the locales as a range.
|
||||
*
|
||||
* In case one of the locales is treated as a range, its
|
||||
* empty fields are considered to match all possible
|
||||
* values of the same field on the other locale.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* Locale("en").Matches(Locale("en-US"), false, false) // false
|
||||
* Locale("en").Matches(Locale("en-US"), true, false) // true
|
||||
*
|
||||
* The latter returns true because the region field on the "en"
|
||||
* locale is being treated as a range and matches any region field
|
||||
* value including "US" of the other locale.
|
||||
*/
|
||||
bool Matches(const MozLocale& aOther, bool aThisRange,
|
||||
bool aOtherRange) const;
|
||||
|
||||
/**
|
||||
* This operation uses CLDR data to build a more specific version
|
||||
* of a generic locale.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* Locale("en").Maximize().AsString(); // "en-Latn-US"
|
||||
*/
|
||||
bool Maximize();
|
||||
|
||||
/**
|
||||
* Clears the variants field of the Locale object.
|
||||
*/
|
||||
void ClearVariants();
|
||||
|
||||
/**
|
||||
* Clears the region field of the Locale object.
|
||||
*/
|
||||
void ClearRegion();
|
||||
|
||||
/**
|
||||
* Marks the locale as invalid which in turns makes
|
||||
* it to be skipped by most LocaleService operations.
|
||||
*/
|
||||
void Invalidate() { mIsWellFormed = false; }
|
||||
|
||||
/**
|
||||
* Compares two locales expecting all fields to match each other.
|
||||
*/
|
||||
bool operator==(const MozLocale& aOther) {
|
||||
// Note: non-well-formed Locale objects are never
|
||||
// treated as equal to anything
|
||||
// (even other non-well-formed ones).
|
||||
return Matches(aOther, false, false);
|
||||
}
|
||||
|
||||
MozLocale(MozLocale&& aOther)
|
||||
: mIsWellFormed(aOther.mIsWellFormed), mRaw(std::move(aOther.mRaw)) {}
|
||||
|
||||
ffi::LanguageIdentifier* Raw() { return mRaw.get(); }
|
||||
const ffi::LanguageIdentifier* Raw() const { return mRaw.get(); }
|
||||
|
||||
private:
|
||||
bool mIsWellFormed;
|
||||
|
||||
// Notice. We had to remove `const` to allow for move constructor, but
|
||||
// that makes it possible to nullptr `mRaw`. Just don't.
|
||||
UniquePtr<ffi::LanguageIdentifier> mRaw;
|
||||
};
|
||||
|
||||
} // namespace intl
|
||||
} // namespace mozilla
|
||||
|
||||
MOZ_DECLARE_RELOCATE_USING_MOVE_CONSTRUCTOR(mozilla::intl::MozLocale)
|
||||
|
||||
#endif /* mozilla_intl_MozLocale_h__ */
|
|
@ -4,9 +4,9 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "Quotes.h"
|
||||
#include "MozLocale.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "mozilla/intl/Locale.h"
|
||||
#include "nsTHashMap.h"
|
||||
#include "nsPrintfCString.h"
|
||||
|
||||
|
@ -54,32 +54,29 @@ const Quotes* QuotesForLang(const nsAtom* aLang) {
|
|||
// Try parsing lang as a Locale (which will also canonicalize case of the
|
||||
// subtags), then see if we can match it with region or script subtags,
|
||||
// if present, or just the primary language tag.
|
||||
Locale loc;
|
||||
auto result = LocaleParser::tryParse(langStr, loc);
|
||||
if (result.isErr()) {
|
||||
MozLocale loc(langStr);
|
||||
if (!loc.IsWellFormed()) {
|
||||
return nullptr;
|
||||
}
|
||||
if (loc.region().present()) {
|
||||
if (!loc.GetRegion().IsEmpty()) {
|
||||
nsAutoCString langAndRegion;
|
||||
langAndRegion.Append(loc.language().span());
|
||||
langAndRegion.Append(loc.GetLanguage());
|
||||
langAndRegion.Append('-');
|
||||
langAndRegion.Append(loc.region().span());
|
||||
langAndRegion.Append(loc.GetRegion());
|
||||
if ((entry = sQuotesForLang->Lookup(langAndRegion).DataPtrOrNull())) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
if (loc.script().present()) {
|
||||
if (!loc.GetScript().IsEmpty()) {
|
||||
nsAutoCString langAndScript;
|
||||
langAndScript.Append(loc.language().span());
|
||||
langAndScript.Append(loc.GetLanguage());
|
||||
langAndScript.Append('-');
|
||||
langAndScript.Append(loc.script().span());
|
||||
langAndScript.Append(loc.GetScript());
|
||||
if ((entry = sQuotesForLang->Lookup(langAndScript).DataPtrOrNull())) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
Span<const char> langAsSpan = loc.language().span();
|
||||
nsAutoCString lang(langAsSpan.data(), langAsSpan.size());
|
||||
if ((entry = sQuotesForLang->Lookup(lang).DataPtrOrNull())) {
|
||||
if ((entry = sQuotesForLang->Lookup(loc.GetLanguage()).DataPtrOrNull())) {
|
||||
return entry;
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ EXPORTS += [
|
|||
|
||||
EXPORTS.mozilla.intl += [
|
||||
"LocaleService.h",
|
||||
"MozLocale.h",
|
||||
"MozLocaleBindings.h",
|
||||
"OSPreferences.h",
|
||||
"Quotes.h",
|
||||
|
@ -40,6 +41,7 @@ EXPORTS.mozilla.intl += [
|
|||
UNIFIED_SOURCES += [
|
||||
"DateTimeFormat.cpp",
|
||||
"LocaleService.cpp",
|
||||
"MozLocale.cpp",
|
||||
"nsLanguageAtomService.cpp",
|
||||
"nsUConvPropertySearch.cpp",
|
||||
"OSPreferences.cpp",
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "mozilla/Encoding.h"
|
||||
#include "mozilla/intl/Locale.h"
|
||||
#include "mozilla/intl/OSPreferences.h"
|
||||
#include "mozilla/ServoBindings.h"
|
||||
#include "mozilla/ServoUtils.h"
|
||||
|
@ -188,28 +187,23 @@ nsStaticAtom* nsLanguageAtomService::GetUncachedLanguageGroup(
|
|||
langStr.Truncate(start.get() - langStr.BeginReading());
|
||||
}
|
||||
|
||||
Locale loc;
|
||||
auto result = LocaleParser::tryParse(langStr, loc);
|
||||
if (result.isOk()) {
|
||||
MozLocale loc(langStr);
|
||||
if (loc.IsWellFormed()) {
|
||||
// Fill in script subtag if not present.
|
||||
if (loc.script().missing()) {
|
||||
if (!loc.addLikelySubtags()) {
|
||||
// Fall back to x-unicode if no match was found
|
||||
return nsGkAtoms::Unicode;
|
||||
}
|
||||
if (loc.GetScript().IsEmpty()) {
|
||||
loc.Maximize();
|
||||
}
|
||||
// Traditional Chinese has separate prefs for Hong Kong / Taiwan;
|
||||
// check the region subtag.
|
||||
if (loc.script().equalTo("Hant")) {
|
||||
if (loc.region().equalTo("HK")) {
|
||||
if (loc.GetScript().EqualsLiteral("Hant")) {
|
||||
if (loc.GetRegion().EqualsLiteral("HK")) {
|
||||
return nsGkAtoms::HongKongChinese;
|
||||
}
|
||||
return nsGkAtoms::Taiwanese;
|
||||
}
|
||||
// Search list of known script subtags that map to langGroup codes.
|
||||
size_t foundIndex;
|
||||
Span<const char> scriptAsSpan = loc.script().span();
|
||||
nsDependentCSubstring script(scriptAsSpan.data(), scriptAsSpan.size());
|
||||
nsDependentCSubstring script = loc.GetScript();
|
||||
if (BinarySearchIf(
|
||||
kScriptLangGroup, 0, ArrayLength(kScriptLangGroup),
|
||||
[script](const auto& entry) -> int {
|
||||
|
@ -221,19 +215,19 @@ nsStaticAtom* nsLanguageAtomService::GetUncachedLanguageGroup(
|
|||
// Script subtag was not recognized (includes "Hani"); check the language
|
||||
// subtag for CJK possibilities so that we'll prefer the appropriate font
|
||||
// rather than falling back to the browser's hardcoded preference.
|
||||
if (loc.language().equalTo("zh")) {
|
||||
if (loc.region().equalTo("HK")) {
|
||||
if (loc.GetLanguage().EqualsLiteral("zh")) {
|
||||
if (loc.GetRegion().EqualsLiteral("HK")) {
|
||||
return nsGkAtoms::HongKongChinese;
|
||||
}
|
||||
if (loc.region().equalTo("TW")) {
|
||||
if (loc.GetRegion().EqualsLiteral("TW")) {
|
||||
return nsGkAtoms::Taiwanese;
|
||||
}
|
||||
return nsGkAtoms::Chinese;
|
||||
}
|
||||
if (loc.language().equalTo("ja")) {
|
||||
if (loc.GetLanguage().EqualsLiteral("ja")) {
|
||||
return nsGkAtoms::Japanese;
|
||||
}
|
||||
if (loc.language().equalTo("ko")) {
|
||||
if (loc.GetLanguage().EqualsLiteral("ko")) {
|
||||
return nsGkAtoms::ko;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
|
||||
#include "gtest/gtest.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/intl/Locale.h"
|
||||
#include "mozilla/intl/LocaleService.h"
|
||||
#include "mozilla/intl/MozLocale.h"
|
||||
#include "mozilla/intl/Collator.h"
|
||||
|
||||
using namespace mozilla::intl;
|
||||
|
@ -138,8 +138,7 @@ TEST(Intl_Locale_LocaleService, GetDefaultLocale)
|
|||
LocaleService::GetInstance()->GetDefaultLocale(locStr);
|
||||
|
||||
ASSERT_FALSE(locStr.IsEmpty());
|
||||
Locale loc;
|
||||
ASSERT_TRUE(LocaleParser::tryParse(locStr, loc).isOk());
|
||||
ASSERT_TRUE(MozLocale(locStr).IsWellFormed());
|
||||
}
|
||||
|
||||
TEST(Intl_Locale_LocaleService, IsAppLocaleRTL)
|
||||
|
|
|
@ -0,0 +1,123 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "mozilla/intl/MozLocale.h"
|
||||
|
||||
using namespace mozilla::intl;
|
||||
|
||||
TEST(Intl_MozLocale_MozLocale, MozLocale)
|
||||
{
|
||||
MozLocale loc = MozLocale("en-US");
|
||||
|
||||
ASSERT_TRUE(loc.GetLanguage().Equals("en"));
|
||||
ASSERT_TRUE(loc.GetRegion().Equals("US"));
|
||||
}
|
||||
|
||||
TEST(Intl_MozLocale_MozLocale, AsString)
|
||||
{
|
||||
MozLocale loc = MozLocale("ja-jp-windows");
|
||||
|
||||
ASSERT_TRUE(loc.AsString().Equals("ja-JP-windows"));
|
||||
}
|
||||
|
||||
TEST(Intl_MozLocale_MozLocale, GetSubTags)
|
||||
{
|
||||
MozLocale loc = MozLocale("en-latn-us-macos");
|
||||
|
||||
ASSERT_TRUE(loc.GetLanguage().Equals("en"));
|
||||
ASSERT_TRUE(loc.GetScript().Equals("Latn"));
|
||||
ASSERT_TRUE(loc.GetRegion().Equals("US"));
|
||||
|
||||
nsTArray<nsCString> variants;
|
||||
loc.GetVariants(variants);
|
||||
ASSERT_TRUE(variants.Length() == 1);
|
||||
ASSERT_TRUE(variants[0].Equals("macos"));
|
||||
}
|
||||
|
||||
TEST(Intl_MozLocale_MozLocale, Matches)
|
||||
{
|
||||
MozLocale loc = MozLocale("en-US");
|
||||
|
||||
MozLocale loc2 = MozLocale("en-GB");
|
||||
ASSERT_FALSE(loc == loc2);
|
||||
|
||||
MozLocale loc3 = MozLocale("en-US");
|
||||
ASSERT_TRUE(loc == loc3);
|
||||
|
||||
MozLocale loc4 = MozLocale("En_us");
|
||||
ASSERT_TRUE(loc == loc4);
|
||||
}
|
||||
|
||||
TEST(Intl_MozLocale_MozLocale, MatchesRange)
|
||||
{
|
||||
MozLocale loc = MozLocale("en-US");
|
||||
|
||||
MozLocale loc2 = MozLocale("en-Latn-US");
|
||||
ASSERT_FALSE(loc == loc2);
|
||||
ASSERT_TRUE(loc.Matches(loc2, true, false));
|
||||
ASSERT_FALSE(loc.Matches(loc2, false, true));
|
||||
ASSERT_FALSE(loc.Matches(loc2, false, false));
|
||||
ASSERT_TRUE(loc.Matches(loc2, true, true));
|
||||
|
||||
MozLocale loc3 = MozLocale("en");
|
||||
ASSERT_FALSE(loc == loc3);
|
||||
ASSERT_TRUE(loc.Matches(loc3, false, true));
|
||||
ASSERT_FALSE(loc.Matches(loc3, true, false));
|
||||
ASSERT_FALSE(loc.Matches(loc3, false, false));
|
||||
ASSERT_TRUE(loc.Matches(loc3, true, true));
|
||||
}
|
||||
|
||||
TEST(Intl_MozLocale_MozLocale, Variants)
|
||||
{
|
||||
MozLocale loc = MozLocale("en-US-UniFon-BasicEng");
|
||||
|
||||
// Make sure that we canonicalize and sort variant tags
|
||||
ASSERT_TRUE(loc.AsString().Equals("en-US-basiceng-unifon"));
|
||||
}
|
||||
|
||||
TEST(Intl_MozLocale_MozLocale, InvalidMozLocale)
|
||||
{
|
||||
MozLocale loc = MozLocale("en-verylongsubtag");
|
||||
ASSERT_FALSE(loc.IsWellFormed());
|
||||
|
||||
MozLocale loc2 = MozLocale("p-te");
|
||||
ASSERT_FALSE(loc2.IsWellFormed());
|
||||
}
|
||||
|
||||
TEST(Intl_MozLocale_MozLocale, ClearRegion)
|
||||
{
|
||||
MozLocale loc = MozLocale("en-US");
|
||||
loc.ClearRegion();
|
||||
ASSERT_TRUE(loc.AsString().Equals("en"));
|
||||
}
|
||||
|
||||
TEST(Intl_MozLocale_MozLocale, ClearVariants)
|
||||
{
|
||||
MozLocale loc = MozLocale("en-US-windows");
|
||||
loc.ClearVariants();
|
||||
ASSERT_TRUE(loc.AsString().Equals("en-US"));
|
||||
}
|
||||
|
||||
TEST(Intl_MozLocale_MozLocale, jaJPmac)
|
||||
{
|
||||
MozLocale loc = MozLocale("ja-JP-mac");
|
||||
ASSERT_TRUE(loc.AsString().Equals("ja-JP-macos"));
|
||||
}
|
||||
|
||||
TEST(Intl_MozLocale_MozLocale, Maximize)
|
||||
{
|
||||
MozLocale loc = MozLocale("en");
|
||||
|
||||
ASSERT_TRUE(loc.GetLanguage().Equals("en"));
|
||||
ASSERT_TRUE(loc.GetScript().IsEmpty());
|
||||
ASSERT_TRUE(loc.GetRegion().IsEmpty());
|
||||
|
||||
ASSERT_TRUE(loc.Maximize());
|
||||
|
||||
ASSERT_TRUE(loc.GetLanguage().Equals("en"));
|
||||
ASSERT_TRUE(loc.GetScript().Equals("Latn"));
|
||||
ASSERT_TRUE(loc.GetRegion().Equals("US"));
|
||||
}
|
|
@ -8,6 +8,7 @@ UNIFIED_SOURCES += [
|
|||
"TestDateTimeFormat.cpp",
|
||||
"TestLocaleService.cpp",
|
||||
"TestLocaleServiceNegotiate.cpp",
|
||||
"TestMozLocale.cpp",
|
||||
"TestOSPreferences.cpp",
|
||||
]
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "OSPreferences.h"
|
||||
#include "mozilla/intl/Locale.h"
|
||||
#include "mozilla/intl/LocaleService.h"
|
||||
#include "mozilla/intl/MozLocale.h"
|
||||
#include "mozilla/WindowsVersion.h"
|
||||
#include "nsReadableUtils.h"
|
||||
|
||||
|
@ -64,14 +64,12 @@ bool OSPreferences::ReadSystemLocales(nsTArray<nsCString>& aLocaleList) {
|
|||
// language code with no region subtag, but the
|
||||
// GlobalizationPreferences API may give us one (e.g. "ja").
|
||||
// So if there's no hyphen in the string at this point, we use
|
||||
// addLikelySubtags to get a suitable region code to
|
||||
// MozLocale::Maximize to get a suitable region code to
|
||||
// go with it.
|
||||
Locale locale;
|
||||
auto result = LocaleParser::tryParse(loc, locale);
|
||||
if (result.isOk() && locale.addLikelySubtags() &&
|
||||
locale.region().present()) {
|
||||
MozLocale locale(loc);
|
||||
if (locale.Maximize() && !locale.GetRegion().IsEmpty()) {
|
||||
loc.Append('-');
|
||||
loc.Append(locale.region().span());
|
||||
loc.Append(locale.GetRegion());
|
||||
}
|
||||
}
|
||||
aLocaleList.AppendElement(loc);
|
||||
|
|
Загрузка…
Ссылка в новой задаче