From b2eff33c9258cb5e0ce754f5a675885222212dba Mon Sep 17 00:00:00 2001 From: Moonchild Date: Thu, 19 May 2022 21:57:58 +0000 Subject: Issue #1210 - Introduce an internal API to get configured application locales. en-US will always be added as a fallback, to make things simpler down the line and avoid error checking all over the place. --- chrome/nsChromeRegistryChrome.cpp | 2 + intl/locale/LocaleService.cpp | 80 ++++++++++++++++++++++++++++++++++++++ intl/locale/LocaleService.h | 82 +++++++++++++++++++++++++++++++++++++++ intl/locale/moz.build | 5 +++ 4 files changed, 169 insertions(+) create mode 100644 intl/locale/LocaleService.cpp create mode 100644 intl/locale/LocaleService.h diff --git a/chrome/nsChromeRegistryChrome.cpp b/chrome/nsChromeRegistryChrome.cpp index 7678183fd3..2037e23d55 100644 --- a/chrome/nsChromeRegistryChrome.cpp +++ b/chrome/nsChromeRegistryChrome.cpp @@ -25,6 +25,7 @@ #include "mozilla/LookAndFeel.h" #include "mozilla/Unused.h" +#include "mozilla/intl/LocaleService.h" #include "nsICommandLine.h" #include "nsILocaleService.h" @@ -385,6 +386,7 @@ nsresult nsChromeRegistryChrome::UpdateSelectedLocale() NS_ASSERTION(obsSvc, "Couldn't get observer service."); obsSvc->NotifyObservers((nsIChromeRegistry*) this, "selected-locale-has-changed", nullptr); + mozilla::intl::LocaleService::GetInstance()->Refresh(); } } diff --git a/intl/locale/LocaleService.cpp b/intl/locale/LocaleService.cpp new file mode 100644 index 0000000000..55542dc1a9 --- /dev/null +++ b/intl/locale/LocaleService.cpp @@ -0,0 +1,80 @@ +/* -*- 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 "LocaleService.h" +#include "mozilla/ClearOnShutdown.h" +#include "mozilla/Services.h" +#include "nsIObserverService.h" +#include "nsIToolkitChromeRegistry.h" + +using namespace mozilla::intl; + +/** + * This function performs the actual language negotiation for the API. + * + * Currently it collects the locale ID used by nsChromeRegistry and + * adds hardcoded "en-US" locale as a fallback. + */ +static void +ReadAppLocales(nsTArray& aRetVal) +{ + nsAutoCString uaLangTag; + nsCOMPtr cr = + mozilla::services::GetToolkitChromeRegistryService(); + if (cr) { + cr->GetSelectedLocale(NS_LITERAL_CSTRING("global"), true, uaLangTag); + } + if (!uaLangTag.IsEmpty()) { + aRetVal.AppendElement(uaLangTag); + } + + if (!uaLangTag.EqualsLiteral("en-US")) { + aRetVal.AppendElement(NS_LITERAL_CSTRING("en-US")); + } +} + +mozilla::StaticAutoPtr LocaleService::sInstance; + +LocaleService* LocaleService::GetInstance() +{ + if (!sInstance) { + sInstance = new LocaleService(); + ClearOnShutdown(&sInstance); + } + return sInstance; +} + +void +LocaleService::GetAppLocales(nsTArray& aRetVal) +{ + if (mAppLocales.IsEmpty()) { + ReadAppLocales(mAppLocales); + } + aRetVal = mAppLocales; +} + +void +LocaleService::GetAppLocale(nsACString& aRetVal) +{ + if (mAppLocales.IsEmpty()) { + ReadAppLocales(mAppLocales); + } + aRetVal = mAppLocales[0]; +} + +void +LocaleService::Refresh() +{ + nsTArray newLocales; + ReadAppLocales(newLocales); + + if (mAppLocales != newLocales) { + mAppLocales = Move(newLocales); + nsCOMPtr obs = mozilla::services::GetObserverService(); + if (obs) { + obs->NotifyObservers(nullptr, "intl:app-locales-changed", nullptr); + } + } +} \ No newline at end of file diff --git a/intl/locale/LocaleService.h b/intl/locale/LocaleService.h new file mode 100644 index 0000000000..e5228418c4 --- /dev/null +++ b/intl/locale/LocaleService.h @@ -0,0 +1,82 @@ +/* -*- 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_LocaleService_h__ +#define mozilla_intl_LocaleService_h__ + +#include "mozilla/StaticPtr.h" +#include "nsString.h" +#include "nsTArray.h" + +namespace mozilla { +namespace intl { + + +/** + * LocaleService is a manager of language negotiation in Gecko. + * + * It's intended to be the core place for collecting available and + * requested languages and negotiating them to produce a fallback + * chain of locales for the application. + */ +class LocaleService +{ +public: + static LocaleService* GetInstance(); + + /** + * Returns a list of locales that the application should be localized to. + * + * The result is a sorted list of valid locale IDs and it should be + * used for all APIs that accept list of locales, like ECMA402 and L10n APIs. + * + * This API always returns at least one locale. + * + * Example: ["en-US", "de", "pl", "sr-Cyrl", "zh-Hans-HK"] + * + * Usage: + * nsTArray appLocales; + * LocaleService::GetInstance()->GetAppLocales(appLocales); + */ + void GetAppLocales(nsTArray& aRetVal); + + /** + * Returns the best locale that the application should be localized to. + * + * The result is a valid locale IDs and it should be + * used for all APIs that do not handle language negotiation. + * + * Where possible, GetAppLocales should be preferred over this API and + * all callsites should handle some form of "best effort" language + * negotiation to respect user preferences in case the use case does + * not have data for the first locale in the list. + * + * Example: "zh-Hans-HK" + * + * Usage: + * nsAutoCString appLocale; + * LocaleService::GetInstance()->GetAppLocale(appLocale); + */ + void GetAppLocale(nsACString& aRetVal); + + /** + * Triggers a refresh of the language negotiation process. + * + * If the result differs from the previous list, it will additionally + * trigger a global event "intl:app-locales-changed". + */ + void Refresh(); + +protected: + nsTArray mAppLocales; + +private: + static StaticAutoPtr sInstance; +}; + +} // intl +} // namespace mozilla + +#endif /* mozilla_intl_LocaleService_h__ */ diff --git a/intl/locale/moz.build b/intl/locale/moz.build index 94a30873ba..2ba1c6679a 100644 --- a/intl/locale/moz.build +++ b/intl/locale/moz.build @@ -35,7 +35,12 @@ EXPORTS += [ 'nsWin32Locale.h', ] +EXPORTS.mozilla.intl += [ + 'LocaleService.h' +] + UNIFIED_SOURCES += [ + 'LocaleService.cpp', 'nsCollation.cpp', 'nsIDateTimeFormat.cpp', 'nsLanguageAtomService.cpp', -- cgit v1.2.3