Bug 1339892 - Refactor mozIntl to have a nicer API and thin logic. r=smaug
authorZibi Braniecki <gandalf@mozilla.com>
Wed, 01 Mar 2017 16:58:11 -0800
changeset 394631 afd35703e5b01482e48fca74bfb29da982af5ec5
parent 394630 8f70ae357674bb83a2c73d2a918e6477f6673c5d
child 394632 077b849d2beb99a92dc9ec8caa8d2023b170dcbc
push id1468
push userasasaki@mozilla.com
push dateMon, 05 Jun 2017 19:31:07 +0000
treeherdermozilla-release@0641fc6ee9d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1339892
milestone54.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1339892 - Refactor mozIntl to have a nicer API and thin logic. r=smaug MozReview-Commit-ID: J4QXXBy7JII
browser/installer/package-manifest.in
mobile/android/installer/package-manifest.in
toolkit/components/mozintl/MozIntl.cpp
toolkit/components/mozintl/MozIntl.h
toolkit/components/mozintl/MozIntlHelper.cpp
toolkit/components/mozintl/MozIntlHelper.h
toolkit/components/mozintl/moz.build
toolkit/components/mozintl/mozIMozIntl.idl
toolkit/components/mozintl/mozIMozIntlHelper.idl
toolkit/components/mozintl/mozIntl.js
toolkit/components/mozintl/mozIntl.manifest
toolkit/components/mozintl/test/test_mozintl.js
toolkit/components/mozintl/test/test_mozintlhelper.js
toolkit/components/mozintl/test/xpcshell.ini
toolkit/content/widgets/datetimepopup.xml
--- 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": {