Bug 1347798 - Create a small per-document bindings for DOMLocalization. r?mossop
MozReview-Commit-ID: DfxIYVxyt9C
--- a/browser/base/content/test/static/browser_all_files_referenced.js
+++ b/browser/base/content/test/static/browser_all_files_referenced.js
@@ -121,17 +121,17 @@ var whitelist = [
// browser/extensions/pdfjs/content/web/viewer.js#7450
{file: "resource://pdf.js/web/debugger.js"},
// These are used in content processes. They are actually referenced.
{file: "resource://shield-recipe-client-content/shield-content-frame.js"},
{file: "resource://shield-recipe-client-content/shield-content-process.js"},
// New L10n API that is not yet used in production
- {file: "resource://gre/modules/DOMLocalization.jsm"},
+ {file: "chrome://global/content/l10n.js"},
// Starting from here, files in the whitelist are bugs that need fixing.
// Bug 1339424 (wontfix?)
{file: "chrome://browser/locale/taskbar.properties",
platforms: ["linux", "macosx"]},
// Bug 1316187
{file: "chrome://global/content/customizeToolbar.xul"},
// Bug 1343837
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -32,18 +32,20 @@ XPCOMUtils.defineLazyModuleGetters(this,
BrowserUsageTelemetry: "resource:///modules/BrowserUsageTelemetry.jsm",
ContentClick: "resource:///modules/ContentClick.jsm",
ContextualIdentityService: "resource://gre/modules/ContextualIdentityService.jsm",
DateTimePickerHelper: "resource://gre/modules/DateTimePickerHelper.jsm",
DirectoryLinksProvider: "resource:///modules/DirectoryLinksProvider.jsm",
ExtensionsUI: "resource:///modules/ExtensionsUI.jsm",
Feeds: "resource:///modules/Feeds.jsm",
FileUtils: "resource://gre/modules/FileUtils.jsm",
+ FileSource: "resource://gre/modules/L10nRegistry.jsm",
FormValidationHandler: "resource:///modules/FormValidationHandler.jsm",
Integration: "resource://gre/modules/Integration.jsm",
+ L10nRegistry: "resource://gre/modules/L10nRegistry.jsm",
LightweightThemeManager: "resource://gre/modules/LightweightThemeManager.jsm",
LoginHelper: "resource://gre/modules/LoginHelper.jsm",
LoginManagerParent: "resource://gre/modules/LoginManagerParent.jsm",
NetUtil: "resource://gre/modules/NetUtil.jsm",
NewTabUtils: "resource://gre/modules/NewTabUtils.jsm",
OS: "resource://gre/modules/osfile.jsm",
PageActions: "resource:///modules/PageActions.jsm",
PageThumbs: "resource://gre/modules/PageThumbs.jsm",
@@ -625,16 +627,24 @@ BrowserGlue.prototype = {
headerURL: "resource:///chrome/browser/content/browser/defaultthemes/compact.header.png",
iconURL: "resource:///chrome/browser/content/browser/defaultthemes/dark.icon.svg",
textcolor: "white",
accentcolor: "black",
author: vendorShortName,
});
}
+
+ // Initialize the default l10n resource sources for L10nRegistry.
+ const locales = [AppConstants.INSTALL_LOCALE];
+ const toolkitSource = new FileSource("toolkit", locales, "resource://gre/localization/{locale}/");
+ L10nRegistry.registerSource(toolkitSource);
+ const appSource = new FileSource("app", locales, "resource://app/localization/{locale}/");
+ L10nRegistry.registerSource(appSource);
+
Services.obs.notifyObservers(null, "browser-ui-startup-complete");
},
_checkForOldBuildUpdates() {
// check for update if our build is old
if (AppConstants.MOZ_UPDATER &&
Services.prefs.getBoolPref("app.update.enabled") &&
Services.prefs.getBoolPref("app.update.checkInstallTime")) {
--- a/intl/l10n/Localization.jsm
+++ b/intl/l10n/Localization.jsm
@@ -52,16 +52,27 @@ class CachedIterable {
async next() {
if (seen.length <= cur) {
seen.push(await iterator.next());
}
return seen[cur++];
}
};
}
+
+ /**
+ * This method allows user to consume the next element from the iterator
+ * into the cache.
+ */
+ touchNext() {
+ const { seen, iterator } = this;
+ if (seen.length === 0 || seen[seen.length - 1].done === false) {
+ seen.push(iterator.next());
+ }
+ }
}
/**
* Specialized version of an Error used to indicate errors that are result
* of a problem during the localization process.
*
* We use them to identify the class of errors the require a fallback
* mechanism to be triggered vs errors that should be reported, but
new file mode 100644
--- /dev/null
+++ b/intl/l10n/jar.mn
@@ -0,0 +1,2 @@
+toolkit.jar:
+ content/global/l10n.js
new file mode 100644
--- /dev/null
+++ b/intl/l10n/l10n.js
@@ -0,0 +1,51 @@
+{
+ const { DOMLocalization } =
+ Components.utils.import("resource://gre/modules/DOMLocalization.jsm");
+
+ /**
+ * Polyfill for document.ready polyfill.
+ * See: https://github.com/whatwg/html/issues/127 for details.
+ *
+ * @returns {Promise}
+ */
+ function documentReady() {
+ const rs = document.readyState;
+ if (rs === 'interactive' || rs === 'completed') {
+ return Promise.resolve();
+ }
+
+ return new Promise(
+ resolve => document.addEventListener(
+ 'readystatechange', resolve, { once: true }
+ )
+ );
+ }
+
+ /**
+ * Scans the `elem` for links with localization resources.
+ *
+ * @param {Element} elem
+ * @returns {Array<string>}
+ */
+ function getResourceLinks(elem) {
+ return Array.from(elem.querySelectorAll('link[rel="localization"]')).map(
+ el => el.getAttribute('href')
+ );
+ }
+
+ const resourceIds = getResourceLinks(document.head || document);
+
+ document.l10n = new DOMLocalization(window, resourceIds);
+
+ // trigger first context to be fetched eagerly
+ document.l10n.ctxs.touchNext();
+
+ document.l10n.ready = documentReady().then(() => {
+ document.l10n.registerObservers();
+ window.addEventListener('unload', () => {
+ document.l10n.unregisterObservers();
+ });
+ document.l10n.connectRoot(document.documentElement);
+ return document.l10n.translateRoots();
+ });
+}
--- a/intl/l10n/moz.build
+++ b/intl/l10n/moz.build
@@ -10,9 +10,11 @@ EXTRA_JS_MODULES += [
'Localization.jsm',
'MessageContext.jsm',
]
XPCSHELL_TESTS_MANIFESTS += ['test/xpcshell.ini']
MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
+JAR_MANIFESTS += ['jar.mn']
+
FINAL_LIBRARY = 'xul'