--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -545,16 +545,21 @@
@RESPATH@/components/PresentationDeviceInfoManager.manifest
@RESPATH@/components/PresentationDeviceInfoManager.js
@RESPATH@/components/BuiltinProviders.manifest
@RESPATH@/components/PresentationControlService.js
@RESPATH@/components/PresentationDataChannelSessionTransport.js
@RESPATH@/components/PresentationDataChannelSessionTransport.manifest
+#ifdef ENABLE_INTL_API
+@RESPATH@/components/mozIntl.manifest
+@RESPATH@/components/mozIntl.js
+#endif
+
#if defined(ENABLE_TESTS) && defined(MOZ_DEBUG)
@RESPATH@/components/TestInterfaceJS.js
@RESPATH@/components/TestInterfaceJS.manifest
@RESPATH@/components/TestInterfaceJSMaplike.js
#endif
; [Extensions]
@RESPATH@/components/extensions-toolkit.manifest
--- a/mobile/android/installer/package-manifest.in
+++ b/mobile/android/installer/package-manifest.in
@@ -393,16 +393,21 @@
@BINPATH@/components/PresentationDataChannelSessionTransport.js
@BINPATH@/components/PresentationDataChannelSessionTransport.manifest
@BINPATH@/components/AndroidCastDeviceProvider.manifest
@BINPATH@/components/AndroidCastDeviceProvider.js
@BINPATH@/components/TVSimulatorService.js
@BINPATH@/components/TVSimulatorService.manifest
+#ifdef ENABLE_INTL_API
+@BINPATH@/components/mozIntl.manifest
+@BINPATH@/components/mozIntl.js
+#endif
+
; Modules
@BINPATH@/modules/*
; Safe Browsing
@BINPATH@/components/nsURLClassifier.manifest
@BINPATH@/components/nsUrlClassifierHashCompleter.js
@BINPATH@/components/nsUrlClassifierListManager.js
@BINPATH@/components/nsUrlClassifierLib.js
rename from toolkit/components/mozintl/MozIntl.cpp
rename to toolkit/components/mozintl/MozIntlHelper.cpp
--- a/toolkit/components/mozintl/MozIntl.cpp
+++ b/toolkit/components/mozintl/MozIntlHelper.cpp
@@ -1,27 +1,27 @@
/* -*- 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 "MozIntl.h"
+#include "MozIntlHelper.h"
#include "jswrapper.h"
#include "mozilla/ModuleUtils.h"
-#define MOZ_MOZINTL_CID \
- { 0x83f8f991, 0x6b81, 0x4dd8, { 0xa0, 0x93, 0x72, 0x0b, 0xfb, 0x67, 0x4d, 0x38 } }
+#define MOZ_MOZINTLHELPER_CID \
+ { 0xb43c96be, 0x2b3a, 0x4dc4, { 0x90, 0xe9, 0xb0, 0x6d, 0x34, 0x21, 0x9b, 0x68 } }
using namespace mozilla;
-NS_IMPL_ISUPPORTS(MozIntl, mozIMozIntl)
+NS_IMPL_ISUPPORTS(MozIntlHelper, mozIMozIntlHelper)
-MozIntl::MozIntl() = default;
+MozIntlHelper::MozIntlHelper() = default;
-MozIntl::~MozIntl() = default;
+MozIntlHelper::~MozIntlHelper() = default;
static nsresult
AddFunctions(JSContext* cx, JS::Handle<JS::Value> val, const JSFunctionSpec* funcs)
{
if (!val.isObject()) {
return NS_ERROR_INVALID_ARG;
}
@@ -35,39 +35,39 @@ AddFunctions(JSContext* cx, JS::Handle<J
if (!JS_DefineFunctions(cx, realIntlObj, funcs)) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
NS_IMETHODIMP
-MozIntl::AddGetCalendarInfo(JS::Handle<JS::Value> val, JSContext* cx)
+MozIntlHelper::AddGetCalendarInfo(JS::Handle<JS::Value> val, JSContext* cx)
{
static const JSFunctionSpec funcs[] = {
JS_SELF_HOSTED_FN("getCalendarInfo", "Intl_getCalendarInfo", 1, 0),
JS_FS_END
};
return AddFunctions(cx, val, funcs);
}
NS_IMETHODIMP
-MozIntl::AddGetDisplayNames(JS::Handle<JS::Value> val, JSContext* cx)
+MozIntlHelper::AddGetDisplayNames(JS::Handle<JS::Value> val, JSContext* cx)
{
static const JSFunctionSpec funcs[] = {
JS_SELF_HOSTED_FN("getDisplayNames", "Intl_getDisplayNames", 2, 0),
JS_FS_END
};
return AddFunctions(cx, val, funcs);
}
NS_IMETHODIMP
-MozIntl::AddPluralRulesConstructor(JS::Handle<JS::Value> val, JSContext* cx)
+MozIntlHelper::AddPluralRulesConstructor(JS::Handle<JS::Value> val, JSContext* cx)
{
if (!val.isObject()) {
return NS_ERROR_INVALID_ARG;
}
JS::Rooted<JSObject*> realIntlObj(cx, js::CheckedUnwrap(&val.toObject()));
if (!realIntlObj) {
return NS_ERROR_INVALID_ARG;
@@ -78,42 +78,42 @@ MozIntl::AddPluralRulesConstructor(JS::H
if (!js::AddPluralRulesConstructor(cx, realIntlObj)) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
NS_IMETHODIMP
-MozIntl::AddGetLocaleInfo(JS::Handle<JS::Value> val, JSContext* cx)
+MozIntlHelper::AddGetLocaleInfo(JS::Handle<JS::Value> val, JSContext* cx)
{
static const JSFunctionSpec funcs[] = {
JS_SELF_HOSTED_FN("getLocaleInfo", "Intl_getLocaleInfo", 1, 0),
JS_FS_END
};
return AddFunctions(cx, val, funcs);
}
-NS_GENERIC_FACTORY_CONSTRUCTOR(MozIntl)
-NS_DEFINE_NAMED_CID(MOZ_MOZINTL_CID);
+NS_GENERIC_FACTORY_CONSTRUCTOR(MozIntlHelper)
+NS_DEFINE_NAMED_CID(MOZ_MOZINTLHELPER_CID);
-static const Module::CIDEntry kMozIntlCIDs[] = {
- { &kMOZ_MOZINTL_CID, false, nullptr, MozIntlConstructor },
+static const Module::CIDEntry kMozIntlHelperCIDs[] = {
+ { &kMOZ_MOZINTLHELPER_CID, false, nullptr, MozIntlHelperConstructor },
{ nullptr }
};
-static const mozilla::Module::ContractIDEntry kMozIntlContracts[] = {
- { "@mozilla.org/mozintl;1", &kMOZ_MOZINTL_CID },
+static const mozilla::Module::ContractIDEntry kMozIntlHelperContracts[] = {
+ { "@mozilla.org/mozintlhelper;1", &kMOZ_MOZINTLHELPER_CID },
{ nullptr }
};
-static const mozilla::Module kMozIntlModule = {
+static const mozilla::Module kMozIntlHelperModule = {
mozilla::Module::kVersion,
- kMozIntlCIDs,
- kMozIntlContracts,
+ kMozIntlHelperCIDs,
+ kMozIntlHelperContracts,
nullptr,
nullptr,
nullptr,
nullptr
};
-NSMODULE_DEFN(mozMozIntlModule) = &kMozIntlModule;
+NSMODULE_DEFN(mozMozIntlHelperModule) = &kMozIntlHelperModule;
rename from toolkit/components/mozintl/MozIntl.h
rename to toolkit/components/mozintl/MozIntlHelper.h
--- a/toolkit/components/mozintl/MozIntl.h
+++ b/toolkit/components/mozintl/MozIntlHelper.h
@@ -1,22 +1,22 @@
/* -*- 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 "mozIMozIntl.h"
+#include "mozIMozIntlHelper.h"
namespace mozilla {
-class MozIntl final : public mozIMozIntl
+class MozIntlHelper final : public mozIMozIntlHelper
{
public:
NS_DECL_ISUPPORTS
- NS_DECL_MOZIMOZINTL
+ NS_DECL_MOZIMOZINTLHELPER
- MozIntl();
+ MozIntlHelper();
private:
- ~MozIntl();
+ ~MozIntlHelper();
};
} // namespace mozilla
--- a/toolkit/components/mozintl/moz.build
+++ b/toolkit/components/mozintl/moz.build
@@ -3,17 +3,23 @@
# 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/.
XPCSHELL_TESTS_MANIFESTS += ['test/xpcshell.ini']
XPIDL_SOURCES += [
'mozIMozIntl.idl',
+ 'mozIMozIntlHelper.idl',
]
XPIDL_MODULE = 'mozintl'
SOURCES += [
- 'MozIntl.cpp',
+ 'MozIntlHelper.cpp',
+]
+
+EXTRA_COMPONENTS += [
+ 'mozIntl.js',
+ 'mozIntl.manifest',
]
FINAL_LIBRARY = 'xul'
--- a/toolkit/components/mozintl/mozIMozIntl.idl
+++ b/toolkit/components/mozintl/mozIMozIntl.idl
@@ -1,21 +1,45 @@
/* -*- 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"
-[scriptable, uuid(9f9bc42e-54f4-11e6-9aed-4b1429ac0ba0)]
+/**
+ * This is a set of APIs that are of general usefulness for user interface
+ * internationalization.
+ *
+ * They're all in various stages of the standardization process through
+ * ECMA402, so they are exposed to privileged content only but are written
+ * in the way to allow for easy migration to standard Intl object once
+ * the appropriate stage of the ECMA402 is achieved.
+ *
+ * The exact structure of the code is a little bit complex because of that:
+ *
+ * 1) The core is in SpiderMonkey together with other Intl APIs
+ *
+ * This allows us to write the code once, stick to the spec language
+ * of the proposal, reuse our ICU bindings in Spidermonkey and use
+ * the code to inform us on refining the spec proposal for the given API itself.
+ *
+ * 2) The MozIntlHelper API exposes the SpiderMonkey APIs
+ *
+ * This helper API allows attaching the new APIs on any regular object.
+ *
+ * 3) The MozIntl API provides the access to those APIs
+ *
+ * This API exposes the actual functionality and wraps around the MozIntlHelper
+ * lazily retrieving and setting the accessors.
+ * On top of that, the API also binds additional functionality like using
+ * current application locale by default, and fetching OS regional preferences
+ * for date time format.
+ */
+[scriptable, uuid(7f63279a-1a29-4ae6-9e7a-dc9684a23530)]
interface mozIMozIntl : nsISupports
{
- [implicit_jscontext] void addGetCalendarInfo(in jsval intlObject);
- [implicit_jscontext] void addGetDisplayNames(in jsval intlObject);
- [implicit_jscontext] void addGetLocaleInfo(in jsval intlObject);
+ jsval getCalendarInfo([optional] in jsval locales);
+ jsval getDisplayNames([optional] in jsval locales, [optional] in jsval options);
+ jsval getLocaleInfo([optional] in jsval locales);
- /**
- * Adds a PluralRules constructor to the given object. This function may only
- * be called once within a realm/global object: calling it multiple times will
- * throw.
- */
- [implicit_jscontext] void addPluralRulesConstructor(in jsval intlObject);
+ jsval createPluralRules([optional] in jsval locales, [optional] in jsval options);
};
copy from toolkit/components/mozintl/mozIMozIntl.idl
copy to toolkit/components/mozintl/mozIMozIntlHelper.idl
--- a/toolkit/components/mozintl/mozIMozIntl.idl
+++ b/toolkit/components/mozintl/mozIMozIntlHelper.idl
@@ -1,17 +1,25 @@
/* -*- 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"
-[scriptable, uuid(9f9bc42e-54f4-11e6-9aed-4b1429ac0ba0)]
-interface mozIMozIntl : nsISupports
+/**
+ * This is an internal helper for mozIMozIntl API. There should be virtually
+ * no reason for you to call this API except from mozIMozIntl implementation.
+ *
+ * This API helps accessing the SpiderMonkey Intl APIs, but it is mozIMozIntl
+ * that exposes the thin wrapper around them that binds the functionality
+ * to Gecko.
+ */
+[scriptable, uuid(189eaa7d-b29a-43a9-b1fb-7658990df940)]
+interface mozIMozIntlHelper : nsISupports
{
[implicit_jscontext] void addGetCalendarInfo(in jsval intlObject);
[implicit_jscontext] void addGetDisplayNames(in jsval intlObject);
[implicit_jscontext] void addGetLocaleInfo(in jsval intlObject);
/**
* Adds a PluralRules constructor to the given object. This function may only
* be called once within a realm/global object: calling it multiple times will
new file mode 100644
--- /dev/null
+++ b/toolkit/components/mozintl/mozIntl.js
@@ -0,0 +1,69 @@
+/* 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/. */
+
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+
+const mozIntlHelper =
+ Cc["@mozilla.org/mozintlhelper;1"].getService(Ci.mozIMozIntlHelper);
+const localeSvc =
+ Cc["@mozilla.org/intl/localeservice;1"].getService(Ci.mozILocaleService);
+
+/**
+ * This helper function retrives currently used app locales, allowing
+ * all mozIntl APIs to use the current app locales unless called with
+ * explicitly listed locales.
+ */
+function getLocales(locales) {
+ if (!locales) {
+ return localeSvc.getAppLocales();
+ }
+ return locales;
+}
+
+class MozIntl {
+ constructor() {
+ this._cache = {};
+ }
+
+ getCalendarInfo(locales, ...args) {
+ if (!this._cache.hasOwnProperty("getCalendarInfo")) {
+ mozIntlHelper.addGetCalendarInfo(this._cache);
+ }
+
+ return this._cache.getCalendarInfo(getLocales(locales), ...args);
+ }
+
+ getDisplayNames(locales, ...args) {
+ if (!this._cache.hasOwnProperty("getDisplayNames")) {
+ mozIntlHelper.addGetDisplayNames(this._cache);
+ }
+
+ return this._cache.getDisplayNames(getLocales(locales), ...args);
+ }
+
+ getLocaleInfo(locales, ...args) {
+ if (!this._cache.hasOwnProperty("getLocaleInfo")) {
+ mozIntlHelper.addGetLocaleInfo(this._cache);
+ }
+
+ return this._cache.getLocaleInfo(getLocales(locales), ...args);
+ }
+
+ createPluralRules(locales, ...args) {
+ if (!this._cache.hasOwnProperty("PluralRules")) {
+ mozIntlHelper.addPluralRulesConstructor(this._cache);
+ }
+
+ return new this._cache.PluralRules(getLocales(locales), ...args);
+ }
+}
+
+MozIntl.prototype.classID = Components.ID("{35ec195a-e8d0-4300-83af-c8a2cc84b4a3}");
+MozIntl.prototype.QueryInterface = XPCOMUtils.generateQI([Ci.mozIMozIntl, Ci.nsISupports]);
+
+var components = [MozIntl];
+this.NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
new file mode 100644
--- /dev/null
+++ b/toolkit/components/mozintl/mozIntl.manifest
@@ -0,0 +1,2 @@
+component {35ec195a-e8d0-4300-83af-c8a2cc84b4a3} mozIntl.js
+contract @mozilla.org/mozintl;1 {35ec195a-e8d0-4300-83af-c8a2cc84b4a3}
--- a/toolkit/components/mozintl/test/test_mozintl.js
+++ b/toolkit/components/mozintl/test/test_mozintl.js
@@ -1,50 +1,27 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function run_test() {
const mozIntl = Components.classes["@mozilla.org/mozintl;1"]
.getService(Components.interfaces.mozIMozIntl);
- test_this_global(mozIntl);
- test_cross_global(mozIntl);
test_methods_presence(mozIntl);
+ test_methods_calling(mozIntl);
ok(true);
}
-function test_this_global(mozIntl) {
- let x = {};
-
- mozIntl.addGetCalendarInfo(x);
- equal(x.getCalendarInfo instanceof Function, true);
- equal(x.getCalendarInfo() instanceof Object, true);
+function test_methods_presence(mozIntl) {
+ equal(mozIntl.getCalendarInfo instanceof Function, true);
+ equal(mozIntl.getDisplayNames instanceof Function, true);
+ equal(mozIntl.getLocaleInfo instanceof Function, true);
+ equal(mozIntl.createPluralRules instanceof Function, true);
}
-function test_cross_global(mozIntl) {
- var global = new Components.utils.Sandbox("https://example.com/");
- var x = global.Object();
-
- mozIntl.addGetCalendarInfo(x);
- var waivedX = Components.utils.waiveXrays(x);
- equal(waivedX.getCalendarInfo instanceof Function, false);
- equal(waivedX.getCalendarInfo instanceof global.Function, true);
- equal(waivedX.getCalendarInfo() instanceof Object, false);
- equal(waivedX.getCalendarInfo() instanceof global.Object, true);
+function test_methods_calling(mozIntl) {
+ let ci = mozIntl.getCalendarInfo('pl');
+ let dn = mozIntl.getDisplayNames('ar');
+ let li = mozIntl.getLocaleInfo('de');
+ let pr = mozIntl.createPluralRules('fr');
+ ok(true);
}
-
-function test_methods_presence(mozIntl) {
- equal(mozIntl.addGetCalendarInfo instanceof Function, true);
- equal(mozIntl.addGetDisplayNames instanceof Function, true);
- equal(mozIntl.addGetLocaleInfo instanceof Function, true);
-
- let x = {};
-
- mozIntl.addGetCalendarInfo(x);
- equal(x.getCalendarInfo instanceof Function, true);
-
- mozIntl.addGetDisplayNames(x);
- equal(x.getDisplayNames instanceof Function, true);
-
- mozIntl.addGetLocaleInfo(x);
- equal(x.getLocaleInfo instanceof Function, true);
-}
new file mode 100644
--- /dev/null
+++ b/toolkit/components/mozintl/test/test_mozintlhelper.js
@@ -0,0 +1,50 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function run_test() {
+ const miHelper = Components.classes["@mozilla.org/mozintlhelper;1"]
+ .getService(Components.interfaces.mozIMozIntlHelper);
+
+ test_this_global(miHelper);
+ test_cross_global(miHelper);
+ test_methods_presence(miHelper);
+
+ ok(true);
+}
+
+function test_this_global(miHelper) {
+ let x = {};
+
+ miHelper.addGetCalendarInfo(x);
+ equal(x.getCalendarInfo instanceof Function, true);
+ equal(x.getCalendarInfo() instanceof Object, true);
+}
+
+function test_cross_global(miHelper) {
+ var global = new Components.utils.Sandbox("https://example.com/");
+ var x = global.Object();
+
+ miHelper.addGetCalendarInfo(x);
+ var waivedX = Components.utils.waiveXrays(x);
+ equal(waivedX.getCalendarInfo instanceof Function, false);
+ equal(waivedX.getCalendarInfo instanceof global.Function, true);
+ equal(waivedX.getCalendarInfo() instanceof Object, false);
+ equal(waivedX.getCalendarInfo() instanceof global.Object, true);
+}
+
+function test_methods_presence(miHelper) {
+ equal(miHelper.addGetCalendarInfo instanceof Function, true);
+ equal(miHelper.addGetDisplayNames instanceof Function, true);
+ equal(miHelper.addGetLocaleInfo instanceof Function, true);
+
+ let x = {};
+
+ miHelper.addGetCalendarInfo(x);
+ equal(x.getCalendarInfo instanceof Function, true);
+
+ miHelper.addGetDisplayNames(x);
+ equal(x.getDisplayNames instanceof Function, true);
+
+ miHelper.addGetLocaleInfo(x);
+ equal(x.getLocaleInfo instanceof Function, true);
+}
--- a/toolkit/components/mozintl/test/xpcshell.ini
+++ b/toolkit/components/mozintl/test/xpcshell.ini
@@ -1,4 +1,5 @@
[DEFAULT]
head =
[test_mozintl.js]
+[test_mozintlhelper.js]
--- a/toolkit/content/widgets/datetimepopup.xml
+++ b/toolkit/content/widgets/datetimepopup.xml
@@ -18,21 +18,18 @@
<field name="dateTimePopupFrame">
this.querySelector("#dateTimePopupFrame");
</field>
<field name="TIME_PICKER_WIDTH" readonly="true">"12em"</field>
<field name="TIME_PICKER_HEIGHT" readonly="true">"21em"</field>
<field name="DATE_PICKER_WIDTH" readonly="true">"23.1em"</field>
<field name="DATE_PICKER_HEIGHT" readonly="true">"20.7em"</field>
<constructor><![CDATA[
- this.l10n = {};
- const mozIntl = Components.classes["@mozilla.org/mozintl;1"]
- .getService(Components.interfaces.mozIMozIntl);
- mozIntl.addGetCalendarInfo(this.l10n);
- mozIntl.addGetDisplayNames(this.l10n);
+ this.mozIntl = Components.classes["@mozilla.org/mozintl;1"]
+ .getService(Components.interfaces.mozIMozIntl);
]]></constructor>
<method name="loadPicker">
<parameter name="type"/>
<parameter name="detail"/>
<body><![CDATA[
this.hidden = false;
this.type = type;
this.pickerState = {};
@@ -221,17 +218,17 @@
break;
}
}
]]></body>
</method>
<method name="getCalendarInfo">
<parameter name="locale"/>
<body><![CDATA[
- const calendarInfo = this.l10n.getCalendarInfo(locale);
+ const calendarInfo = this.mozIntl.getCalendarInfo(locale);
// Day of week from calendarInfo starts from 1 as Sunday to 7 as Saturday,
// so they need to be mapped to JavaScript convention with 0 as Sunday
// and 6 as Saturday
let firstDayOfWeek = calendarInfo.firstDayOfWeek - 1,
weekendStart = calendarInfo.weekendStart - 1,
weekendEnd = calendarInfo.weekendEnd - 1;
@@ -254,17 +251,17 @@
}
]]></body>
</method>
<method name="getDisplayNames">
<parameter name="locale"/>
<parameter name="keys"/>
<parameter name="style"/>
<body><![CDATA[
- const displayNames = this.l10n.getDisplayNames(locale, {keys, style});
+ const displayNames = this.mozIntl.getDisplayNames(locale, {keys, style});
return keys.map(key => displayNames.values[key]);
]]></body>
</method>
<method name="handleEvent">
<parameter name="aEvent"/>
<body><![CDATA[
switch (aEvent.type) {
case "load": {