summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chrome/nsChromeRegistryChrome.cpp2
-rw-r--r--dom/base/nsGlobalWindow.cpp12
-rw-r--r--dom/base/nsGlobalWindow.h3
-rw-r--r--dom/webidl/Window.webidl15
-rw-r--r--intl/build/nsI18nModule.cpp3
-rw-r--r--intl/locale/LocaleService.cpp105
-rw-r--r--intl/locale/LocaleService.h88
-rw-r--r--intl/locale/moz.build6
-rw-r--r--intl/locale/mozILocaleService.idl48
-rw-r--r--intl/locale/nsLocaleConstructors.h8
10 files changed, 290 insertions, 0 deletions
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/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp
index c6b35a9bf0..be1c2463e5 100644
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -49,6 +49,7 @@
#include "nsNetUtil.h"
#include "nsVariant.h"
#include "nsPrintfCString.h"
+#include "mozilla/intl/LocaleService.h"
// Helper Classes
#include "nsJSUtils.h"
@@ -14794,6 +14795,17 @@ nsGlobalWindow::CreateWorklet(ErrorResult& aRv)
return worklet.forget();
}
+void
+nsGlobalWindow::GetAppLocales(nsTArray<nsString>& aLocales)
+{
+ nsTArray<nsCString> appLocales;
+ mozilla::intl::LocaleService::GetInstance()->GetAppLocales(appLocales);
+
+ for (uint32_t i = 0; i < appLocales.Length(); i++) {
+ aLocales.AppendElement(NS_ConvertUTF8toUTF16(appLocales[i]));
+ }
+}
+
template class nsPIDOMWindow<mozIDOMWindowProxy>;
template class nsPIDOMWindow<mozIDOMWindow>;
template class nsPIDOMWindow<nsISupports>;
diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h
index e42835a0b2..43270e80d9 100644
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -897,6 +897,9 @@ public:
already_AddRefed<mozilla::dom::Worklet>
CreateWorklet(mozilla::ErrorResult& aRv);
+ void
+ GetAppLocales(nsTArray<nsString>& aLocales);
+
protected:
bool AlertOrConfirm(bool aAlert, const nsAString& aMessage,
nsIPrincipal& aSubjectPrincipal,
diff --git a/dom/webidl/Window.webidl b/dom/webidl/Window.webidl
index 1b98042473..8a6b05a88e 100644
--- a/dom/webidl/Window.webidl
+++ b/dom/webidl/Window.webidl
@@ -486,3 +486,18 @@ callback IdleRequestCallback = void (IdleDeadline deadline);
partial interface Window {
[ChromeOnly] readonly attribute boolean isSecureContextIfOpenerIgnored;
};
+
+partial interface Window {
+/**
+ * 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"]
+ */
+ [Func="IsChromeOrXBL"]
+ sequence<DOMString> getAppLocales();
+}; \ No newline at end of file
diff --git a/intl/build/nsI18nModule.cpp b/intl/build/nsI18nModule.cpp
index 9959d3d6fb..62ac7e47df 100644
--- a/intl/build/nsI18nModule.cpp
+++ b/intl/build/nsI18nModule.cpp
@@ -44,6 +44,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsEntityConverter)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSaveAsCharset)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsUnicodeNormalizer)
+NS_DEFINE_NAMED_CID(MOZ_LOCALESERVICE_CID);
NS_DEFINE_NAMED_CID(NS_LBRK_CID);
NS_DEFINE_NAMED_CID(NS_WBRK_CID);
NS_DEFINE_NAMED_CID(NS_SEMANTICUNITSCANNER_CID);
@@ -73,6 +74,7 @@ NS_DEFINE_NAMED_CID(NS_DATETIMEFORMAT_CID);
#endif
static const mozilla::Module::CIDEntry kIntlCIDs[] = {
+ { &kMOZ_LOCALESERVICE_CID, false, nullptr, mozilla::intl::LocaleServiceConstructor },
{ &kNS_LBRK_CID, false, nullptr, nsJISx4051LineBreakerConstructor },
{ &kNS_WBRK_CID, false, nullptr, nsSampleWordBreakerConstructor },
{ &kNS_SEMANTICUNITSCANNER_CID, false, nullptr, nsSemanticUnitScannerConstructor },
@@ -104,6 +106,7 @@ static const mozilla::Module::CIDEntry kIntlCIDs[] = {
};
static const mozilla::Module::ContractIDEntry kIntlContracts[] = {
+ { MOZ_LOCALESERVICE_CONTRACTID, &kMOZ_LOCALESERVICE_CID },
{ NS_LBRK_CONTRACTID, &kNS_LBRK_CID },
{ NS_WBRK_CONTRACTID, &kNS_WBRK_CID },
{ NS_SEMANTICUNITSCANNER_CONTRACTID, &kNS_SEMANTICUNITSCANNER_CID },
diff --git a/intl/locale/LocaleService.cpp b/intl/locale/LocaleService.cpp
new file mode 100644
index 0000000000..7a84ae2449
--- /dev/null
+++ b/intl/locale/LocaleService.cpp
@@ -0,0 +1,105 @@
+/* -*- 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;
+
+NS_IMPL_ISUPPORTS(LocaleService, mozILocaleService)
+
+mozilla::StaticRefPtr<LocaleService> LocaleService::sInstance;
+
+/**
+ * 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<nsCString>& aRetVal)
+{
+ nsAutoCString uaLangTag;
+ nsCOMPtr<nsIToolkitChromeRegistry> 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"));
+ }
+}
+
+LocaleService*
+LocaleService::GetInstance()
+{
+ if (!sInstance) {
+ sInstance = new LocaleService();
+ ClearOnShutdown(&sInstance);
+ }
+ return sInstance;
+}
+
+void
+LocaleService::GetAppLocales(nsTArray<nsCString>& aRetVal)
+{
+ if (mAppLocales.IsEmpty()) {
+ ReadAppLocales(mAppLocales);
+ }
+ aRetVal = mAppLocales;
+}
+
+void
+LocaleService::Refresh()
+{
+ nsTArray<nsCString> newLocales;
+ ReadAppLocales(newLocales);
+
+ if (mAppLocales != newLocales) {
+ mAppLocales = Move(newLocales);
+ nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+ if (obs) {
+ obs->NotifyObservers(nullptr, "intl:app-locales-changed", nullptr);
+ }
+ }
+}
+
+/**
+ * mozILocaleService methods
+ */
+NS_IMETHODIMP
+LocaleService::GetAppLocales(uint32_t* aCount, char*** aOutArray)
+{
+ if (mAppLocales.IsEmpty()) {
+ ReadAppLocales(mAppLocales);
+ }
+
+ *aCount = mAppLocales.Length();
+ *aOutArray = static_cast<char**>(moz_xmalloc(*aCount * sizeof(char*)));
+
+ for (uint32_t i = 0; i < *aCount; i++) {
+ (*aOutArray)[i] = moz_xstrdup(mAppLocales[i].get());
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+LocaleService::GetAppLocale(nsACString& aRetVal)
+{
+ if (mAppLocales.IsEmpty()) {
+ ReadAppLocales(mAppLocales);
+ }
+ aRetVal = mAppLocales[0];
+ return NS_OK;
+} \ No newline at end of file
diff --git a/intl/locale/LocaleService.h b/intl/locale/LocaleService.h
new file mode 100644
index 0000000000..e41e3c8d1e
--- /dev/null
+++ b/intl/locale/LocaleService.h
@@ -0,0 +1,88 @@
+/* -*- 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"
+
+#include "mozILocaleService.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 mozILocaleService
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_MOZILOCALESERVICE
+
+ /**
+ * Create (if necessary) and return a raw pointer to the singleton instance.
+ * Use this accessor in C++ code that just wants to call a method on the
+ * instance, but does not need to hold a reference, as in
+ * nsAutoCString str;
+ * LocaleService::GetInstance()->GetAppLocale(str);
+ */
+ static LocaleService* GetInstance();
+
+ /**
+ * Return an addRef'd pointer to the singleton instance. This is used by the
+ * XPCOM constructor that exists to support usage from JS.
+ */
+ static already_AddRefed<LocaleService> GetInstanceAddRefed()
+ {
+ return RefPtr<LocaleService>(GetInstance()).forget();
+ }
+
+ /**
+ * 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<nsCString> appLocales;
+ * LocaleService::GetInstance()->GetAppLocales(appLocales);
+ *
+ * (See mozILocaleService.idl for a JS-callable version of this.)
+ */
+ void GetAppLocales(nsTArray<nsCString>& 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<nsCString> mAppLocales;
+
+private:
+ virtual ~LocaleService() {};
+
+ static StaticRefPtr<LocaleService> sInstance;
+};
+
+} // intl
+} // namespace mozilla
+
+#endif /* mozilla_intl_LocaleService_h__ */
diff --git a/intl/locale/moz.build b/intl/locale/moz.build
index 94a30873ba..1f6d44253e 100644
--- a/intl/locale/moz.build
+++ b/intl/locale/moz.build
@@ -15,6 +15,7 @@ else:
DIRS += ['unix']
XPIDL_SOURCES += [
+ 'mozILocaleService.idl',
'nsICollation.idl',
'nsILocale.idl',
'nsILocaleService.idl',
@@ -35,7 +36,12 @@ EXPORTS += [
'nsWin32Locale.h',
]
+EXPORTS.mozilla.intl += [
+ 'LocaleService.h'
+]
+
UNIFIED_SOURCES += [
+ 'LocaleService.cpp',
'nsCollation.cpp',
'nsIDateTimeFormat.cpp',
'nsLanguageAtomService.cpp',
diff --git a/intl/locale/mozILocaleService.idl b/intl/locale/mozILocaleService.idl
new file mode 100644
index 0000000000..297ae7c063
--- /dev/null
+++ b/intl/locale/mozILocaleService.idl
@@ -0,0 +1,48 @@
+/* -*- Mode: IDL; 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 "nsISupports.idl"
+
+%{C++
+// Define Contractid and CID
+#define MOZ_LOCALESERVICE_CID \
+ { 0x92735ff4, 0x6384, 0x4ad6, { 0x85, 0x08, 0x75, 0x70, 0x10, 0xe1, 0x49, 0xee } }
+
+#define MOZ_LOCALESERVICE_CONTRACTID "@mozilla.org/intl/localeservice;1"
+%}
+
+[scriptable, uuid(C27F8983-B48B-4D1A-92D7-FEB8106F212D)]
+interface mozILocaleService : nsISupports
+{
+ /**
+ * 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"]
+ *
+ * (See LocaleService.h for a more C++-friendly version of this.)
+ */
+ void getAppLocales([optional] out unsigned long aCount,
+ [retval, array, size_is(aCount)] out string aLocales);
+
+ /**
+ * Returns the best locale that the application should be localized to.
+ *
+ * The result is a valid locale ID 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"
+ */
+ ACString getAppLocale();
+};
diff --git a/intl/locale/nsLocaleConstructors.h b/intl/locale/nsLocaleConstructors.h
index 2d2e579740..8bf4ad6fe4 100644
--- a/intl/locale/nsLocaleConstructors.h
+++ b/intl/locale/nsLocaleConstructors.h
@@ -14,6 +14,7 @@
#include "nsIServiceManager.h"
#include "nsLanguageAtomService.h"
#include "nsPlatformCharset.h"
+#include "LocaleService.h"
#if defined(XP_MACOSX)
#define USE_MAC_LOCALE
@@ -61,6 +62,13 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsCollationFactory)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsLanguageAtomService)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPlatformCharset, Init)
+namespace mozilla {
+namespace intl {
+NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(LocaleService,
+ LocaleService::GetInstanceAddRefed)
+}
+}
+
#ifdef XP_WIN
NS_GENERIC_FACTORY_CONSTRUCTOR(nsCollationWin)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDateTimeFormatWin)