[Pkg-mozext-commits] [greasemonkey] 01/25: Initial localization support.
David Prévot
taffit at moszumanska.debian.org
Wed Sep 17 21:14:00 UTC 2014
This is an automated email from the git hooks/post-receive script.
taffit pushed a commit to branch master
in repository greasemonkey.
commit 41c0f273ae7da2c169e4582363483d5184408463
Author: Ventero <ventero at ventero.de>
Date: Sun Jul 27 14:32:07 2014 +0200
Initial localization support.
This adds support for localized script description/name.
Refs #1963.
---
content/browser.js | 2 +-
content/install.js | 4 +--
content/scriptprefs.js | 2 +-
modules/addons4.js | 6 ++--
modules/parseScript.js | 13 +++++++--
modules/remoteScript.js | 2 +-
modules/script.js | 58 ++++++++++++++++++++++++++++++++++++++
modules/util/getBestLocaleMatch.js | 32 +++++++++++++++++++++
modules/util/getPreferredLocale.js | 17 +++++++++++
9 files changed, 126 insertions(+), 10 deletions(-)
diff --git a/content/browser.js b/content/browser.js
index fde7448..21a609a 100644
--- a/content/browser.js
+++ b/content/browser.js
@@ -331,7 +331,7 @@ function GM_showPopup(aEvent) {
function appendScriptAfter(script, point) {
if (script.needsUninstall) return;
var mi = document.createElement("menuitem");
- mi.setAttribute("label", script.name);
+ mi.setAttribute("label", script.localized.name);
mi.script = script;
mi.setAttribute("type", "checkbox");
mi.setAttribute("checked", script.enabled.toString());
diff --git a/content/install.js b/content/install.js
index 6be9027..6ebece3 100644
--- a/content/install.js
+++ b/content/install.js
@@ -37,12 +37,12 @@ function init() {
var desc = document.getElementById('scriptDescription');
desc.appendChild(document.createElementNS(gHtmlNs, 'strong'));
- desc.firstChild.appendChild(document.createTextNode(gScript.name));
+ desc.firstChild.appendChild(document.createTextNode(gScript.localized.name));
if (gScript.version) {
desc.appendChild(document.createTextNode(' ' + gScript.version));
}
desc.appendChild(document.createElementNS(gHtmlNs, 'br'));
- desc.appendChild(document.createTextNode(gScript.description));
+ desc.appendChild(document.createTextNode(gScript.localized.description));
if (gRemoteScript.done) {
// Download finished before we could open, fake a progress event.
diff --git a/content/scriptprefs.js b/content/scriptprefs.js
index d2bc748..f4068f4 100644
--- a/content/scriptprefs.js
+++ b/content/scriptprefs.js
@@ -14,7 +14,7 @@ var gUserTabEl;
window.addEventListener('load', function() {
// I wanted "%s" but % is reserved in a DTD and I don't know the literal.
- document.title = document.title.replace('!!', gScript.name);
+ document.title = document.title.replace('!!', gScript.localized.name);
var gTabboxEl = document.getElementsByTagName('tabbox')[0];
gUserTabEl = gTabboxEl.tabs.getItemAtIndex(0);
diff --git a/modules/addons4.js b/modules/addons4.js
index c0eab51..eee9ab7 100755
--- a/modules/addons4.js
+++ b/modules/addons4.js
@@ -91,9 +91,9 @@ function ScriptAddon(aScript) {
this.id = aScript.id + SCRIPT_ID_SUFFIX;
this.forceUpdate = false;
- this.name = this._script.name;
+ this.name = this._script.localized.name;
this.version = this._script.version;
- this.description = this._script.description;
+ this.description = this._script.localized.decription;
this.iconURL = this._script.icon && this._script.icon.fileURL;
this.updateDate = this._script.modifiedDate;
this.providesUpdatesSecurely = aScript.updateIsSecure;
@@ -255,7 +255,7 @@ function ScriptInstallFactoryByAddon(aAddon) {
function ScriptInstall(aAddon) {
var newScript = aAddon._script.availableUpdate;
this.iconURL = newScript.icon.fileURL;
- this.name = newScript.name;
+ this.name = newScript.localized.name;
this.version = newScript.version;
this._script = aAddon._script;
diff --git a/modules/parseScript.js b/modules/parseScript.js
index e255951..32ebb10 100644
--- a/modules/parseScript.js
+++ b/modules/parseScript.js
@@ -13,7 +13,7 @@ var gIoService = Components.classes["@mozilla.org/network/io-service;1"]
var gLineSplitRegexp = /.+/g;
var gAllMetaRegexp = new RegExp(
'^// ==UserScript==([\\s\\S]*?)^// ==/UserScript==', 'm');
-var gMetaLineRegexp = new RegExp('// @(\\S+)(?:\\s+(.*))?');
+var gMetaLineRegexp = new RegExp('// @([^\\s:]+)(?::([a-zA-Z-]+))?(?:\\s+(.*))?');
var gStringBundle = Components
.classes["@mozilla.org/intl/stringbundle;1"]
.getService(Components.interfaces.nsIStringBundleService)
@@ -55,11 +55,20 @@ function parse(aSource, aUri, aFailWhenMissing, aNoMetaOk) {
if (!match) continue;
var header = match[1];
- var value = match[2] || null;
+ var locale = match[2];
+ var value = match[3] || null;
switch (header) {
case 'description':
case 'name':
+ if (locale) {
+ if (!script._locales[locale])
+ script._locales[locale] = {};
+
+ script._locales[locale][header] = value;
+ break;
+ }
+ // fall-through if no locale given
case 'namespace':
case 'version':
case 'updateMetaStatus':
diff --git a/modules/remoteScript.js b/modules/remoteScript.js
index dc23035..65e5166 100644
--- a/modules/remoteScript.js
+++ b/modules/remoteScript.js
@@ -372,7 +372,7 @@ RemoteScript.prototype.install = function(aOldScript, aOnlyDependencies) {
// Let the user know we're all done.
if (!this._silent) {
GM_notification(
- "'" + this.script.name + "' "
+ "'" + this.script.localized.name + "' "
+ stringBundleBrowser.GetStringFromName(this.messageName),
this.messageName);
}
diff --git a/modules/script.js b/modules/script.js
index e399b0c..89c9106 100644
--- a/modules/script.js
+++ b/modules/script.js
@@ -42,6 +42,10 @@ function Script(configNode) {
this._id = null;
this._installTime = null;
this._includes = [];
+ // All available localized properties.
+ this._locales = {};
+ // The best localized matches for the current browser locale.
+ this._localized = null;
this._matches = [];
this._modifiedTime = null;
this._name = 'user-script';
@@ -139,6 +143,35 @@ function Script_getDependencies() {
Script.prototype.__defineGetter__('description',
function Script_getDescription() { return this._description; });
+Script.prototype.__defineGetter__('localized',
+function Script_getLocalizedDescription() {
+ // We can't simply return this._locales[locale], as the best match for name
+ // and description might be for different locales (e.g. if an exact match is
+ // only provided for one of them).
+ if (!this._localized) {
+ var locales = this._locales;
+ var preferred = GM_util.getPreferredLocale();
+
+ function getBestLocalization(aProp) {
+ var available = Object.keys(locales).filter(function(locale) {
+ return !!locales[locale][aProp];
+ });
+
+ var bestMatch = GM_util.getBestLocaleMatch(preferred, available);
+ if (!bestMatch) return null;
+
+ return locales[bestMatch][aProp];
+ }
+
+ this._localized = {
+ description: getBestLocalization("description") || this._description,
+ name: getBestLocalization("name") || this._name
+ };
+ }
+
+ return this._localized
+});
+
Script.prototype.__defineGetter__('downloadURL',
function Script_getDownloadUrl() { return this._downloadURL; });
Script.prototype.__defineSetter__('downloadURL',
@@ -342,6 +375,11 @@ Script.prototype._loadFromConfigNode = function(node) {
scriptResource._charset = childNode.getAttribute("charset");
this._resources.push(scriptResource);
break;
+ case "Name":
+ case "Description":
+ var lang = childNode.getAttribute("lang");
+ if (!this._locales[lang]) this._locales[lang] = {};
+ this._locales[lang][childNode.nodeName.toLowerCase()] = childNode.textContent;
}
}
@@ -363,6 +401,8 @@ Script.prototype.toConfigNode = function(doc) {
node.appendChild(doc.createTextNode(content));
scriptNode.appendChild(doc.createTextNode("\n\t\t"));
scriptNode.appendChild(node);
+
+ return node;
}
function addArrayNodes(aName, aArray) {
@@ -371,6 +411,11 @@ Script.prototype.toConfigNode = function(doc) {
}
}
+ function addLocaleNode(aName, aLang, aContent) {
+ var node = addNode(aName, aContent);
+ node.setAttribute("lang", lang);
+ }
+
addArrayNodes('Exclude', this._excludes);
addArrayNodes('Grant', this._grants);
addArrayNodes('Include', this._includes);
@@ -406,6 +451,15 @@ Script.prototype.toConfigNode = function(doc) {
scriptNode.appendChild(resourceNode);
}
+
+ for (var lang in this._locales) {
+ if (this._locales[lang].name)
+ addLocaleNode("Name", lang, this._locales[lang].name);
+
+ if (this._locales[lang].description)
+ addLocaleNode("Description", lang, this._locales[lang].description);
+ }
+
scriptNode.appendChild(doc.createTextNode("\n\t"));
scriptNode.setAttribute("basedir", this._basedir);
@@ -470,6 +524,8 @@ Script.prototype.info = function() {
'excludes': this.excludes,
// 'icon': ???,
'includes': this.includes,
+ 'localizedDescription': this.localized.description,
+ 'localizedName': this.localized.name,
'matches': matches,
'name': this.name,
'namespace': this.namespace,
@@ -559,6 +615,8 @@ Script.prototype.updateFromNewScript = function(newScript, safeWin) {
this._includes = newScript._includes;
this._matches = newScript._matches;
this._description = newScript._description;
+ this._localized = newScript._localized;
+ this._locales = newScript._locales;
this._runAt = newScript._runAt;
this._version = newScript._version;
this.downloadURL = newScript.downloadURL;
diff --git a/modules/util/getBestLocaleMatch.js b/modules/util/getBestLocaleMatch.js
new file mode 100644
index 0000000..d0d8e75
--- /dev/null
+++ b/modules/util/getBestLocaleMatch.js
@@ -0,0 +1,32 @@
+Components.utils.import("resource://gre/modules/Services.jsm");
+Components.utils.import('resource://greasemonkey/util.js');
+
+const EXPORTED_SYMBOLS = ['getBestLocaleMatch'];
+
+// This function tries to find the best matching locale.
+// Locales should be given in the form "lang[-COUNTRY]".
+// If an exact match (i.e. both lang and country match) can be found, it is
+// returned. Otherwise, a partial match based on the lang part is attempted.
+// Partial matches without country are preferred over lang matches with
+// non-matching country.
+// If no locale matches, null is returned.
+function getBestLocaleMatch(aPreferred, aAvailable) {
+ var preferredLang = aPreferred.split("-")[0];
+
+ var langMatch, partialMatch = null;
+ for (var i = 0, current; current = aAvailable[i]; i++) {
+ // Both lang and country match
+ if (current == aPreferred)
+ return current;
+
+ if (current == preferredLang) {
+ // Only lang matches, no country
+ langMatch = current;
+ } else if (current.split("-")[0] == preferredLang) {
+ // Only lang matches, non-matching country
+ partialMatch = current;
+ }
+ }
+
+ return langMatch || partialMatch;
+}
diff --git a/modules/util/getPreferredLocale.js b/modules/util/getPreferredLocale.js
new file mode 100644
index 0000000..4732cd4
--- /dev/null
+++ b/modules/util/getPreferredLocale.js
@@ -0,0 +1,17 @@
+Components.utils.import("resource://gre/modules/Services.jsm");
+Components.utils.import('resource://greasemonkey/util.js');
+
+const EXPORTED_SYMBOLS = ['getPreferredLocale'];
+
+var preferredLocale = (function() {
+ var matchOS = Services.prefs.getBoolPref("intl.locale.matchOS");
+
+ if (matchOS)
+ return Services.locale.getLocaleComponentForUserAgent();
+
+ return Services.prefs.getCharPref("general.useragent.locale") || "en-US";
+})();
+
+function getPreferredLocale() {
+ return preferredLocale;
+}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-mozext/greasemonkey.git
More information about the Pkg-mozext-commits
mailing list