[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