[Pkg-javascript-commits] [pdf.js] 48/72: Update to latest version of webL10n
David Prévot
taffit at moszumanska.debian.org
Wed Mar 18 20:15:59 UTC 2015
This is an automated email from the git hooks/post-receive script.
taffit pushed a commit to branch master
in repository pdf.js.
commit f20c5ddf99dc412ba9965940567ae515277267de
Author: Rob Wu <rob at robwu.nl>
Date: Tue Mar 10 15:46:20 2015 +0100
Update to latest version of webL10n
New commits since last update:
- https://github.com/fabi1cazenave/webL10n/compare/b5e072c...7d351d51b1
- Plus unmerged patch from PDF.js: https://github.com/fabi1cazenave/webL10n/pull/62
(the PDF.js-specific changes will be applied in a separate commit)
---
external/webL10n/l10n.js | 396 ++++++++++++++++++++++++++++++++++-------------
1 file changed, 288 insertions(+), 108 deletions(-)
diff --git a/external/webL10n/l10n.js b/external/webL10n/l10n.js
index 6c9421b..9c46564 100644
--- a/external/webL10n/l10n.js
+++ b/external/webL10n/l10n.js
@@ -19,14 +19,8 @@
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
-/*
- Additional modifications for PDF.js project:
- - Disables language initialization on page loading;
- - Removes consoleWarn and consoleLog and use console.log/warn directly.
- - Removes window._ assignment.
-*/
-
-/*jshint browser: true, devel: true, globalstrict: true */
+
+/*jshint browser: true, devel: true, es5: true, globalstrict: true */
'use strict';
document.webL10n = (function(window, document, undefined) {
@@ -54,6 +48,29 @@ document.webL10n = (function(window, document, undefined) {
/**
+ * Debug helpers
+ *
+ * gDEBUG == 0: don't display any console message
+ * gDEBUG == 1: display only warnings, not logs
+ * gDEBUG == 2: display all console messages
+ */
+
+ var gDEBUG = 1;
+
+ function consoleLog(message) {
+ if (gDEBUG >= 2) {
+ console.log('[l10n] ' + message);
+ }
+ }
+
+ function consoleWarn(message) {
+ if (gDEBUG) {
+ console.warn('[l10n] ' + message);
+ }
+ }
+
+
+ /**
* DOM helpers for the so-called "HTML API".
*
* These functions are written for modern browsers. For old versions of IE,
@@ -85,7 +102,7 @@ document.webL10n = (function(window, document, undefined) {
try {
args = JSON.parse(l10nArgs);
} catch (e) {
- console.warn('could not parse arguments for #' + l10nId);
+ consoleWarn('could not parse arguments for #' + l10nId);
}
}
return { id: l10nId, args: args };
@@ -98,14 +115,14 @@ document.webL10n = (function(window, document, undefined) {
document.dispatchEvent(evtObject);
}
- function xhrLoadText(url, onSuccess, onFailure, asynchronous) {
+ function xhrLoadText(url, onSuccess, onFailure) {
onSuccess = onSuccess || function _onSuccess(data) {};
onFailure = onFailure || function _onFailure() {
- console.warn(url + ' not found.');
+ consoleWarn(url + ' not found.');
};
var xhr = new XMLHttpRequest();
- xhr.open('GET', url, asynchronous);
+ xhr.open('GET', url, gAsyncResourceLoading);
if (xhr.overrideMimeType) {
xhr.overrideMimeType('text/plain; charset=utf-8');
}
@@ -174,8 +191,10 @@ document.webL10n = (function(window, document, undefined) {
}
// parse *.properties text data into an l10n dictionary
- function parseProperties(text) {
- var dictionary = [];
+ // If gAsyncResourceLoading is false, then the callback will be called
+ // synchronously. Otherwise it is called asynchronously.
+ function parseProperties(text, parsedPropertiesCallback) {
+ var dictionary = {};
// token expressions
var reBlank = /^\s*|\s*$/;
@@ -185,57 +204,69 @@ document.webL10n = (function(window, document, undefined) {
var reSplit = /^([^=\s]*)\s*=\s*(.+)$/; // TODO: escape EOLs with '\'
// parse the *.properties file into an associative array
- function parseRawLines(rawText, extendedSyntax) {
+ function parseRawLines(rawText, extendedSyntax, parsedRawLinesCallback) {
var entries = rawText.replace(reBlank, '').split(/[\r\n]+/);
var currentLang = '*';
var genericLang = lang.split('-', 1)[0];
var skipLang = false;
var match = '';
- for (var i = 0; i < entries.length; i++) {
- var line = entries[i];
+ function nextEntry() {
+ // Use infinite loop instead of recursion to avoid reaching the
+ // maximum recursion limit for content with many lines.
+ while (true) {
+ if (!entries.length) {
+ parsedRawLinesCallback();
+ return;
+ }
+ var line = entries.shift();
- // comment or blank line?
- if (reComment.test(line))
- continue;
+ // comment or blank line?
+ if (reComment.test(line))
+ continue;
- // the extended syntax supports [lang] sections and @import rules
- if (extendedSyntax) {
- if (reSection.test(line)) { // section start?
+ // the extended syntax supports [lang] sections and @import rules
+ if (extendedSyntax) {
match = reSection.exec(line);
- // RFC 4646, section 4.4, "All comparisons MUST be performed
- // in a case-insensitive manner."
- currentLang = match[1].toLowerCase();
- skipLang = (currentLang !== '*') &&
- (currentLang !== lang) && (currentLang !== genericLang);
- continue;
- } else if (skipLang) {
- continue;
- }
- if (reImport.test(line)) { // @import rule?
+ if (match) { // section start?
+ // RFC 4646, section 4.4, "All comparisons MUST be performed
+ // in a case-insensitive manner."
+
+ currentLang = match[1].toLowerCase();
+ skipLang = (currentLang !== '*') &&
+ (currentLang !== lang) && (currentLang !== genericLang);
+ continue;
+ } else if (skipLang) {
+ continue;
+ }
match = reImport.exec(line);
- loadImport(baseURL + match[1]); // load the resource synchronously
+ if (match) { // @import rule?
+ loadImport(baseURL + match[1], nextEntry);
+ return;
+ }
}
- }
- // key-value pair
- var tmp = line.match(reSplit);
- if (tmp && tmp.length == 3) {
- dictionary[tmp[1]] = evalString(tmp[2]);
+ // key-value pair
+ var tmp = line.match(reSplit);
+ if (tmp && tmp.length == 3) {
+ dictionary[tmp[1]] = evalString(tmp[2]);
+ }
}
}
+ nextEntry();
}
// import another *.properties file
- function loadImport(url) {
+ function loadImport(url, callback) {
xhrLoadText(url, function(content) {
- parseRawLines(content, false); // don't allow recursive imports
- }, null, false); // load synchronously
+ parseRawLines(content, false, callback); // don't allow recursive imports
+ }, null);
}
// fill the dictionary
- parseRawLines(text, true);
- return dictionary;
+ parseRawLines(text, true, function() {
+ parsedPropertiesCallback(dictionary);
+ });
}
// load and parse l10n data (warning: global variables are used here)
@@ -243,29 +274,30 @@ document.webL10n = (function(window, document, undefined) {
gTextData += response; // mostly for debug
// parse *.properties text data into an l10n dictionary
- var data = parseProperties(response);
-
- // find attribute descriptions, if any
- for (var key in data) {
- var id, prop, index = key.lastIndexOf('.');
- if (index > 0) { // an attribute has been specified
- id = key.substring(0, index);
- prop = key.substr(index + 1);
- } else { // no attribute: assuming text content by default
- id = key;
- prop = gTextProp;
- }
- if (!gL10nData[id]) {
- gL10nData[id] = {};
+ parseProperties(response, function(data) {
+
+ // find attribute descriptions, if any
+ for (var key in data) {
+ var id, prop, index = key.lastIndexOf('.');
+ if (index > 0) { // an attribute has been specified
+ id = key.substring(0, index);
+ prop = key.substr(index + 1);
+ } else { // no attribute: assuming text content by default
+ id = key;
+ prop = gTextProp;
+ }
+ if (!gL10nData[id]) {
+ gL10nData[id] = {};
+ }
+ gL10nData[id][prop] = data[key];
}
- gL10nData[id][prop] = data[key];
- }
- // trigger callback
- if (successCallback) {
- successCallback();
- }
- }, failureCallback, gAsyncResourceLoading);
+ // trigger callback
+ if (successCallback) {
+ successCallback();
+ }
+ });
+ }, failureCallback);
}
// load and parse all resources for the specified locale
@@ -289,7 +321,7 @@ document.webL10n = (function(window, document, undefined) {
// we might have a pre-compiled dictionary instead
var dict = getL10nDictionary();
if (dict && dict.locales && dict.default_locale) {
- console.log('using the embedded JSON directory, early way out');
+ consoleLog('using the embedded JSON directory, early way out');
gL10nData = dict.locales[lang];
if (!gL10nData) {
var defaultLocale = dict.default_locale.toLowerCase();
@@ -305,7 +337,7 @@ document.webL10n = (function(window, document, undefined) {
}
callback();
} else {
- console.log('no resource to load, early way out');
+ consoleLog('no resource to load, early way out');
}
// early way out
fireL10nReadyEvent(lang);
@@ -328,24 +360,23 @@ document.webL10n = (function(window, document, undefined) {
// load all resource files
function L10nResourceLink(link) {
var href = link.href;
- var type = link.type;
+ // Note: If |gAsyncResourceLoading| is false, then the following callbacks
+ // are synchronously called.
this.load = function(lang, callback) {
- var applied = lang;
parseResource(href, lang, callback, function() {
- console.warn(href + ' not found.');
- applied = '';
+ consoleWarn(href + ' not found.');
+ // lang not found, used default resource instead
+ consoleWarn('"' + lang + '" resource not found');
+ gLanguage = '';
+ // Resource not loaded, but we still need to call the callback.
+ callback();
});
- return applied; // return lang if found, an empty string if not found
};
}
for (var i = 0; i < langCount; i++) {
var resource = new L10nResourceLink(langLinks[i]);
- var rv = resource.load(lang, onResourceLoaded);
- if (rv != lang) { // lang not found, used default resource instead
- console.warn('"' + lang + '" resource not found');
- gLanguage = '';
- }
+ resource.load(lang, onResourceLoaded);
}
}
@@ -764,7 +795,7 @@ document.webL10n = (function(window, document, undefined) {
// return a function that gives the plural form name for a given integer
var index = locales2rules[lang.replace(/-.*$/, '')];
if (!(index in pluralRules)) {
- console.warn('plural form unknown for [' + lang + ']');
+ consoleWarn('plural form unknown for [' + lang + ']');
return function() { return 'other'; };
}
return pluralRules[index];
@@ -811,7 +842,7 @@ document.webL10n = (function(window, document, undefined) {
function getL10nData(key, args, fallback) {
var data = gL10nData[key];
if (!data) {
- console.warn('#' + key + ' is undefined.');
+ consoleWarn('#' + key + ' is undefined.');
if (!fallback) {
return null;
}
@@ -861,28 +892,17 @@ document.webL10n = (function(window, document, undefined) {
// replace {{arguments}} with their values
function substArguments(str, args, key) {
- var reArgs = /\{\{\s*(.+?)\s*\}\}/;
- var match = reArgs.exec(str);
- while (match) {
- if (!match || match.length < 2)
- return str; // argument key not found
-
- var arg = match[1];
- var sub = '';
+ var reArgs = /\{\{\s*(.+?)\s*\}\}/g;
+ return str.replace(reArgs, function(matched_text, arg) {
if (args && arg in args) {
- sub = args[arg];
- } else if (arg in gL10nData) {
- sub = gL10nData[arg][gTextProp];
- } else {
- console.log('argument {{' + arg + '}} for #' + key + ' is undefined.');
- return str;
+ return args[arg];
}
-
- str = str.substring(0, match.index) + sub +
- str.substr(match.index + match[0].length);
- match = reArgs.exec(str);
- }
- return str;
+ if (arg in gL10nData) {
+ return gL10nData[arg];
+ }
+ consoleLog('argument {{' + arg + '}} for #' + key + ' is undefined.');
+ return matched_text;
+ });
}
// translate an HTML element
@@ -894,7 +914,7 @@ document.webL10n = (function(window, document, undefined) {
// get the related l10n object
var data = getL10nData(l10n.id, l10n.args);
if (!data) {
- console.warn('#' + l10n.id + ' is undefined.');
+ consoleWarn('#' + l10n.id + ' is undefined.');
return;
}
@@ -962,6 +982,151 @@ document.webL10n = (function(window, document, undefined) {
translateElement(element);
}
+
+ /**
+ * Startup & Public API
+ *
+ * Warning: this part of the code contains browser-specific chunks --
+ * that's where obsolete browsers, namely IE8 and earlier, are handled.
+ *
+ * Unlike the rest of the lib, this section is not shared with FirefoxOS/Gaia.
+ */
+
+ // load the default locale on startup
+ function l10nStartup() {
+ gReadyState = 'interactive';
+
+ // most browsers expose the UI language as `navigator.language'
+ // but IE uses `navigator.userLanguage' instead
+ var userLocale = navigator.language || navigator.userLanguage;
+ consoleLog('loading [' + userLocale + '] resources, ' +
+ (gAsyncResourceLoading ? 'asynchronously.' : 'synchronously.'));
+
+ // load the default locale and translate the document if required
+ if (document.documentElement.lang === userLocale) {
+ loadLocale(userLocale);
+ } else {
+ loadLocale(userLocale, translateFragment);
+ }
+ }
+
+ // browser-specific startup
+ if (document.addEventListener) { // modern browsers and IE9+
+ if (document.readyState === 'loading') {
+ // the document is not fully loaded yet: wait for DOMContentLoaded.
+ document.addEventListener('DOMContentLoaded', l10nStartup);
+ } else {
+ // l10n.js is being loaded with <script defer> or <script async>,
+ // the DOM is ready for parsing.
+ window.setTimeout(l10nStartup);
+ }
+ } else if (window.attachEvent) { // IE8 and before (= oldIE)
+ // TODO: check if jQuery is loaded (CSS selector + JSON + events)
+
+ // dummy `console.log' and `console.warn' functions
+ if (!window.console) {
+ consoleLog = function(message) {}; // just ignore console.log calls
+ consoleWarn = function(message) {
+ if (gDEBUG) {
+ alert('[l10n] ' + message); // vintage debugging, baby!
+ }
+ };
+ }
+
+ // XMLHttpRequest for IE6
+ if (!window.XMLHttpRequest) {
+ xhrLoadText = function(url, onSuccess, onFailure) {
+ onSuccess = onSuccess || function _onSuccess(data) {};
+ onFailure = onFailure || function _onFailure() {
+ consoleWarn(url + ' not found.');
+ };
+ var xhr = new ActiveXObject('Microsoft.XMLHTTP');
+ xhr.open('GET', url, gAsyncResourceLoading);
+ xhr.onreadystatechange = function() {
+ if (xhr.readyState == 4) {
+ if (xhr.status == 200) {
+ onSuccess(xhr.responseText);
+ } else {
+ onFailure();
+ }
+ }
+ };
+ xhr.send(null);
+ };
+ }
+
+ // worst hack ever for IE6 and IE7
+ if (!window.JSON) {
+ getL10nAttributes = function(element) {
+ if (!element)
+ return {};
+ var l10nId = element.getAttribute('data-l10n-id'),
+ l10nArgs = element.getAttribute('data-l10n-args'),
+ args = {};
+ if (l10nArgs) try {
+ args = eval(l10nArgs); // XXX yeah, I know...
+ } catch (e) {
+ consoleWarn('could not parse arguments for #' + l10nId);
+ }
+ return { id: l10nId, args: args };
+ };
+ }
+
+ // override `getTranslatableChildren' and `getL10nResourceLinks'
+ if (!document.querySelectorAll) {
+ getTranslatableChildren = function(element) {
+ if (!element)
+ return [];
+ var nodes = element.getElementsByTagName('*'),
+ l10nElements = [],
+ n = nodes.length;
+ for (var i = 0; i < n; i++) {
+ if (nodes[i].getAttribute('data-l10n-id'))
+ l10nElements.push(nodes[i]);
+ }
+ return l10nElements;
+ };
+ getL10nResourceLinks = function() {
+ var links = document.getElementsByTagName('link'),
+ l10nLinks = [],
+ n = links.length;
+ for (var i = 0; i < n; i++) {
+ if (links[i].type == 'application/l10n')
+ l10nLinks.push(links[i]);
+ }
+ return l10nLinks;
+ };
+ }
+
+ // override `getL10nDictionary'
+ if (!window.JSON || !document.querySelectorAll) {
+ getL10nDictionary = function() {
+ var scripts = document.getElementsByName('script');
+ for (var i = 0; i < scripts.length; i++) {
+ if (scripts[i].type == 'application/l10n') {
+ return eval(scripts[i].innerHTML);
+ }
+ }
+ return null;
+ };
+ }
+
+ // fire non-standard `localized' DOM events
+ if (document.createEventObject && !document.createEvent) {
+ fireL10nReadyEvent = function(lang) {
+ // hack to simulate a custom event in IE:
+ // to catch this event, add an event handler to `onpropertychange'
+ document.documentElement.localized = 1;
+ };
+ }
+
+ // startup for IE<9
+ window.attachEvent('onload', function() {
+ gTextProp = document.textContent === null ? 'textContent' : 'innerText';
+ l10nStartup();
+ });
+ }
+
// cross-browser API (sorry, oldIE doesn't support getters & setters)
return {
// get a localized string
@@ -990,17 +1155,20 @@ document.webL10n = (function(window, document, undefined) {
// get|set the document language
getLanguage: function() { return gLanguage; },
- setLanguage: function(lang) { loadLocale(lang, translateFragment); },
+ setLanguage: function(lang, callback) {
+ loadLocale(lang, function() {
+ if (callback)
+ callback();
+ translateFragment();
+ });
+ },
// get the direction (ltr|rtl) of the current language
getDirection: function() {
// http://www.w3.org/International/questions/qa-scripts
// Arabic, Hebrew, Farsi, Pashto, Urdu
var rtlList = ['ar', 'he', 'fa', 'ps', 'ur'];
-
- // use the short language code for "full" codes like 'ar-sa' (issue 5440)
- var shortCode = gLanguage.split('-')[0];
-
+ var shortCode = gLanguage.split('-', 1)[0];
return (rtlList.indexOf(shortCode) >= 0) ? 'rtl' : 'ltr';
},
@@ -1013,12 +1181,18 @@ document.webL10n = (function(window, document, undefined) {
if (!callback) {
return;
} else if (gReadyState == 'complete' || gReadyState == 'interactive') {
- window.setTimeout(callback);
+ window.setTimeout(function() {
+ callback();
+ });
} else if (document.addEventListener) {
- document.addEventListener('localized', callback);
+ document.addEventListener('localized', function once() {
+ document.removeEventListener('localized', once);
+ callback();
+ });
} else if (document.attachEvent) {
- document.documentElement.attachEvent('onpropertychange', function(e) {
+ document.documentElement.attachEvent('onpropertychange', function once(e) {
if (e.propertyName === 'localized') {
+ document.documentElement.detachEvent('onpropertychange', once);
callback();
}
});
@@ -1026,3 +1200,9 @@ document.webL10n = (function(window, document, undefined) {
}
};
}) (window, document);
+
+// gettext-like shortcut for document.webL10n.get
+if (window._ === undefined) {
+ var _ = document.webL10n.get;
+}
+
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/pdf.js.git
More information about the Pkg-javascript-commits
mailing list