Bug 1475903 - Add mozIDOMLocalization API. r=mossop

In order to use DOMLocalization from C++ we need an XPIDL interface.
mozIDOMLocalization exposes the class and functionality allowing DocumentL10n to hook into it.

MozReview-Commit-ID: GPMhw61LPEg

--HG--
extra : rebase_source : 62d5909d9db8858c2ad1b4234d6f9b9be8da7efd
This commit is contained in:
Zibi Braniecki 2018-06-22 13:14:23 -07:00
Родитель 8421040c69
Коммит 0ce3ff104d
11 изменённых файлов: 318 добавлений и 0 удалений

Просмотреть файл

@ -364,6 +364,9 @@
@RESPATH@/browser/components/startupRecorder.js
#endif
@RESPATH@/components/mozDOMLocalization.js
@RESPATH@/components/mozDOMLocalization.manifest
; [Extensions]
@RESPATH@/components/extensions-toolkit.manifest
@RESPATH@/components/extension-process-script.js

Просмотреть файл

@ -11,6 +11,17 @@ EXTRA_JS_MODULES += [
'MessageContext.jsm',
]
XPIDL_SOURCES += [
'mozIDOMLocalization.idl',
]
XPIDL_MODULE = 'locale'
EXTRA_COMPONENTS += [
'mozDOMLocalization.js',
'mozDOMLocalization.manifest',
]
XPCSHELL_TESTS_MANIFESTS += ['test/xpcshell.ini']
MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']

Просмотреть файл

@ -0,0 +1,9 @@
const { XPCOMUtils } = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm", {});
const { DOMLocalization } = ChromeUtils.import("resource://gre/modules/DOMLocalization.jsm", {});
DOMLocalization.prototype.classID =
Components.ID("{29cc3895-8835-4c5b-b53a-0c0d1a458dee}");
DOMLocalization.prototype.QueryInterface =
ChromeUtils.generateQI([Ci.mozIDOMLocalization, Ci.nsISupportsWeakReference]);
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([DOMLocalization]);

Просмотреть файл

@ -0,0 +1,2 @@
component {29cc3895-8835-4c5b-b53a-0c0d1a458dee} mozDOMLocalization.js
contract @mozilla.org/intl/domlocalization;1 {29cc3895-8835-4c5b-b53a-0c0d1a458dee}

Просмотреть файл

@ -0,0 +1,27 @@
/* -*- 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"
webidl Document;
webidl Element;
[scriptable, uuid(7c468500-541f-4fe0-98c9-92a53b63ec8d)]
interface mozIDOMLocalization : nsISupports
{
unsigned long addResourceIds(in Array<AString> resourceIds);
unsigned long removeResourceIds(in Array<AString> resourceIds);
Promise formatMessages(in Array<jsval> aKeys);
Promise formatValues(in Array<jsval> aKeys);
Promise formatValue(in DOMString aId, [optional] in jsval aArgs);
Promise translateFragment(in Element aElement);
Promise translateElements(in Array<Element> aElements);
void connectRoot(in Element aElement);
Promise translateRoots();
readonly attribute Promise ready;
};

Просмотреть файл

@ -14,3 +14,7 @@
[dom/test_domloc_overlay_missing_children.html]
[dom/test_domloc_overlay_sanitized.html]
[dom/test_domloc.xul]
[dom/test_mozdom_translateElements.html]
[dom/test_mozdom_translateFragment.html]
[dom/test_mozdom_translateRoots.html]

Просмотреть файл

@ -0,0 +1,60 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Test mozIDOMLocalization.translateElements</title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
<script type="application/javascript">
"use strict";
const domLocalization =
Cc["@mozilla.org/intl/domlocalization;1"].createInstance(
Ci.mozIDOMLocalization);
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm", {});
const { L10nRegistry, FileSource } =
ChromeUtils.import("resource://gre/modules/L10nRegistry.jsm", {});
const fs = {
"/localization/en-US/browser/menu.ftl": `
title = Hello World
link =
.title = Click me
`,
};
const originalLoad = L10nRegistry.load;
const originalRequested = Services.locale.getRequestedLocales();
L10nRegistry.load = async function(url) {
return fs.hasOwnProperty(url) ? fs[url] : false;
};
const source = new FileSource("test", ["en-US"], "/localization/{locale}");
L10nRegistry.registerSource(source);
window.onload = async function() {
SimpleTest.waitForExplicitFinish();
domLocalization.addResourceIds(["/browser/menu.ftl"], 1);
const p1 = document.querySelectorAll("p")[0];
const link1 = document.querySelectorAll("a")[0];
await domLocalization.translateElements([p1, link1], 2);
is(p1.textContent, "Hello World");
is(link1.getAttribute("title"), "Click me");
// Cleanup
L10nRegistry.removeSource(source.name);
L10nRegistry.load = originalLoad;
Services.locale.setRequestedLocales(originalRequested);
SimpleTest.finish();
};
</script>
</head>
<body>
<p data-l10n-id="title" />
<a data-l10n-id="link" />
</body>
</html>

Просмотреть файл

@ -0,0 +1,61 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Test mozIDOMLocalization.translateFragment</title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
<script type="application/javascript">
"use strict";
const domLocalization =
Cc["@mozilla.org/intl/domlocalization;1"].createInstance(
Ci.mozIDOMLocalization);
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm", {});
const { L10nRegistry, FileSource } =
ChromeUtils.import("resource://gre/modules/L10nRegistry.jsm", {});
const fs = {
"/localization/en-US/browser/menu.ftl": `
title = Hello World
subtitle = Welcome to Fluent
`,
};
const originalLoad = L10nRegistry.load;
const originalRequested = Services.locale.getRequestedLocales();
L10nRegistry.load = async function(url) {
return fs.hasOwnProperty(url) ? fs[url] : false;
};
const source = new FileSource("test", ["en-US"], "/localization/{locale}");
L10nRegistry.registerSource(source);
window.onload = async function() {
SimpleTest.waitForExplicitFinish();
domLocalization.addResourceIds(["/browser/menu.ftl"], 1);
const frag = document.querySelectorAll("div")[0];
const h1 = document.querySelectorAll("h1")[0];
const p1 = document.querySelectorAll("p")[0];
await domLocalization.translateFragment(frag);
is(h1.textContent, "Hello World");
is(p1.textContent, "Welcome to Fluent");
// Cleanup
L10nRegistry.removeSource(source.name);
L10nRegistry.load = originalLoad;
Services.locale.setRequestedLocales(originalRequested);
SimpleTest.finish();
};
</script>
</head>
<body>
<div>
<h1 data-l10n-id="title" />
<p data-l10n-id="subtitle" />
</div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,68 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Test mozIDOMLocalization.connectRoot and translateRoots</title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
<script type="application/javascript">
"use strict";
const domLocalization =
Cc["@mozilla.org/intl/domlocalization;1"].createInstance(
Ci.mozIDOMLocalization);
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm", {});
const { L10nRegistry, FileSource } =
ChromeUtils.import("resource://gre/modules/L10nRegistry.jsm", {});
const fs = {
"/localization/en-US/browser/menu.ftl": `
title = Hello World
title2 = Hello Another World
`,
};
const originalLoad = L10nRegistry.load;
const originalRequested = Services.locale.getRequestedLocales();
L10nRegistry.load = async function(url) {
return fs.hasOwnProperty(url) ? fs[url] : false;
};
const source = new FileSource("test", ["en-US"], "/localization/{locale}");
L10nRegistry.registerSource(source);
window.onload = async function() {
SimpleTest.waitForExplicitFinish();
domLocalization.addResourceIds(["/browser/menu.ftl"], 1);
const frag1 = document.querySelectorAll("div")[0];
const frag2 = document.querySelectorAll("div")[1];
const h1 = document.querySelectorAll("h1")[0];
const h2 = document.querySelectorAll("h2")[0];
domLocalization.connectRoot(frag1);
domLocalization.connectRoot(frag2);
await domLocalization.translateRoots();
is(h1.textContent, "Hello World");
is(h2.textContent, "Hello Another World");
// Cleanup
L10nRegistry.removeSource(source.name);
L10nRegistry.load = originalLoad;
Services.locale.setRequestedLocales(originalRequested);
SimpleTest.finish();
};
</script>
</head>
<body>
<div>
<h1 data-l10n-id="title"></h1>
</div>
<div>
<h2 data-l10n-id="title2"></h2>
</div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,72 @@
const domLocalization =
Cc["@mozilla.org/intl/domlocalization;1"].createInstance(
Ci.mozIDOMLocalization);
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm", {});
const { L10nRegistry, FileSource } =
ChromeUtils.import("resource://gre/modules/L10nRegistry.jsm", {});
const fs = {
"/localization/en-US/browser/menu.ftl": "key = [en] Value",
};
const originalLoad = L10nRegistry.load;
const originalRequested = Services.locale.getRequestedLocales();
L10nRegistry.load = async function(url) {
return fs.hasOwnProperty(url) ? fs[url] : false;
};
const source = new FileSource("test", ["en-US"], "/localization/{locale}");
L10nRegistry.registerSource(source);
add_task(function test_methods_presence() {
equal(typeof domLocalization.addResourceIds, "function");
equal(typeof domLocalization.removeResourceIds, "function");
equal(typeof domLocalization.formatMessages, "function");
equal(typeof domLocalization.formatValues, "function");
equal(typeof domLocalization.formatValue, "function");
equal(typeof domLocalization.translateFragment, "function");
equal(typeof domLocalization.translateElements, "function");
equal(typeof domLocalization.connectRoot, "function");
equal(typeof domLocalization.translateRoots, "function");
equal(typeof domLocalization.ready, "object");
});
add_task(function test_add_remove_resources() {
equal(domLocalization.addResourceIds(["./path1.ftl", "./path2.ftl"], 2), 2);
equal(domLocalization.removeResourceIds(["./path1.ftl", "./path2.ftl"], 2), 0);
});
add_task(async function test_format_messages() {
domLocalization.addResourceIds(["/browser/menu.ftl"], 1);
let msgs = await domLocalization.formatMessages([{"id": "key"}], 1);
equal(msgs.length, 1);
equal(msgs[0].value, "[en] Value");
});
add_task(async function test_format_values() {
let msgs = await domLocalization.formatValues([{"id": "key"}], 1);
equal(msgs.length, 1);
equal(msgs[0], "[en] Value");
});
add_task(async function test_format_value() {
let msg = await domLocalization.formatValue("key");
equal(msg, "[en] Value");
});
add_task(async function test_ready() {
await domLocalization.ready;
equal(1, 1);
});
add_task(function cleanup() {
L10nRegistry.sources.clear();
L10nRegistry.load = originalLoad;
Services.locale.setRequestedLocales(originalRequested);
});

Просмотреть файл

@ -5,4 +5,5 @@ head =
[test_l10nregistry.js]
[test_localization.js]
[test_messagecontext.js]
[test_mozdomlocalization.js]
[test_pseudo.js]