summaryrefslogtreecommitdiff
path: root/src/static/js/html10n.js
diff options
context:
space:
mode:
authorLuiza Pagliari <lpagliari@gmail.com>2017-08-15 11:09:56 -0300
committerGitHub <noreply@github.com>2017-08-15 11:09:56 -0300
commited5213c9a25830767c87cfba19c18ab71d837b94 (patch)
tree9a6bed037169fa819c1419be812bb4aa634f3c2a /src/static/js/html10n.js
parent6bcaa00a4ba70320a390457c90dbf699d0e4a4b9 (diff)
downloadetherpad-lite-ed5213c9a25830767c87cfba19c18ab71d837b94.zip
Revert "[feat] Update l10n lib (#3248)" (#3249)
This reverts commit 6bcaa00a4ba70320a390457c90dbf699d0e4a4b9.
Diffstat (limited to 'src/static/js/html10n.js')
-rw-r--r--src/static/js/html10n.js219
1 files changed, 86 insertions, 133 deletions
diff --git a/src/static/js/html10n.js b/src/static/js/html10n.js
index f2d79ab4..eecbaa0a 100644
--- a/src/static/js/html10n.js
+++ b/src/static/js/html10n.js
@@ -21,30 +21,18 @@
* IN THE SOFTWARE.
*/
window.html10n = (function(window, document, undefined) {
-
+
// fix console
- var console = window.console
- function interceptConsole(method){
- if (!console) return function() {}
-
- var original = console[method]
-
- // do sneaky stuff
- if (original.bind){
- // Do this for normal browsers
- return original.bind(console)
- }else{
- return function() {
- // Do this for IE
- var message = Array.prototype.slice.apply(arguments).join(' ')
- original(message)
- }
+ (function() {
+ var noop = function() {};
+ var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];
+ var console = (window.console = window.console || {});
+ for (var i = 0; i < names.length; ++i) {
+ if (!console[names[i]]) {
+ console[names[i]] = noop;
}
- }
- var consoleLog = interceptConsole('log')
- , consoleWarn = interceptConsole('warn')
- , consoleError = interceptConsole('warn')
-
+ }
+ }());
// fix Array#forEach in IE
// taken from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
@@ -92,7 +80,7 @@ window.html10n = (function(window, document, undefined) {
return -1;
}
}
-
+
/**
* MicroEvent - to make any js object an event emitter (server or browser)
*/
@@ -128,7 +116,7 @@ window.html10n = (function(window, document, undefined) {
destObject[props[i]] = MicroEvent.prototype[props[i]];
}
}
-
+
/**
* Loader
* The loader is responsible for loading
@@ -139,7 +127,7 @@ window.html10n = (function(window, document, undefined) {
this.cache = {} // file => contents
this.langs = {} // lang => strings
}
-
+
Loader.prototype.load = function(lang, cb) {
if(this.langs[lang]) return cb()
@@ -148,23 +136,23 @@ window.html10n = (function(window, document, undefined) {
for (var i=0, n=this.resources.length; i < n; i++) {
this.fetch(this.resources[i], lang, function(e) {
reqs++;
- if(e) consoleWarn(e)
-
+ if(e) console.warn(e)
+
if (reqs < n) return;// Call back once all reqs are completed
cb && cb()
})
}
}
}
-
+
Loader.prototype.fetch = function(href, lang, cb) {
var that = this
-
+
if (this.cache[href]) {
this.parse(lang, href, this.cache[href], cb)
return;
}
-
+
var xhr = new XMLHttpRequest()
xhr.open('GET', href, /*async: */true)
if (xhr.overrideMimeType) {
@@ -184,7 +172,7 @@ window.html10n = (function(window, document, undefined) {
};
xhr.send(null);
}
-
+
Loader.prototype.parse = function(lang, currHref, data, cb) {
if ('object' != typeof data) {
cb(new Error('A file couldn\'t be parsed as json.'))
@@ -192,7 +180,7 @@ window.html10n = (function(window, document, undefined) {
}
// dat alng ain't here, man!
- if (!data) {
+ if (!data[lang]) {
var msg = 'Couldn\'t find translations for '+lang
, l
if(~lang.indexOf('-')) lang = lang.split('-')[0] // then let's try related langs
@@ -204,7 +192,7 @@ window.html10n = (function(window, document, undefined) {
}
if(lang != l) return cb(new Error(msg))
}
-
+
if ('string' == typeof data[lang]) {
// Import rule
@@ -212,7 +200,7 @@ window.html10n = (function(window, document, undefined) {
var importUrl = data[lang]
// relative path
- if(data[lang].indexOf("http") != 0 && data[lang].indexOf("/") != 0) {
+ if(data[lang].indexOf("http") != 0 && data[lang].indexOf("/") != 0) {
importUrl = currHref+"/../"+data[lang]
}
@@ -220,40 +208,29 @@ window.html10n = (function(window, document, undefined) {
return
}
- if ('object' != typeof data) {
+ if ('object' != typeof data[lang]) {
cb(new Error('Translations should be specified as JSON objects!'))
return
}
- this.langs[lang] = data
+ this.langs[lang] = data[lang]
// TODO: Also store accompanying langs
cb()
}
-
-
+
+
/**
* The html10n object
*/
- var html10n =
+ var html10n =
{ language : null
}
MicroEvent.mixin(html10n)
-
+
html10n.macros = {}
html10n.rtl = ["ar","dv","fa","ha","he","ks","ku","ps","ur","yi"]
-
- /**
- * Language-Script fallbacks for Language-Region language tags, for languages that
- * varies heavily on writing form and two-part locale expansion is not feasible.
- * See also: https://tools.ietf.org/html/rfc4646 (RFC 4646)
- */
- html10n.scripts = {
- 'zh-tw': 'zh-hant',
- 'zh-hk': 'zh-hant',
- 'zh-cn': 'zh-hans'
- }
-
+
/**
* Get rules for plural forms (shared with JetPack), see:
* http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html
@@ -658,7 +635,7 @@ window.html10n = (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)) {
- consoleWarn('plural form unknown for [' + lang + ']');
+ console.warn('plural form unknown for [' + lang + ']');
return function() { return 'other'; };
}
return pluralRules[index];
@@ -691,44 +668,25 @@ window.html10n = (function(window, document, undefined) {
return str;
};
-
- /** Prepare localization context:
- *
- * - Populate translations with strings for the indicated languages
- * - adding in non-qualified versions of language codes immediately
- * after any qualified (e.g., "en" for "en-GB")
- * - Trigger "localized" event.
- *
- * @param {array} langs: diminishing-precedence lang codes, or one string.
+
+ /**
+ * Localize a document
+ * @param langs An array of lang codes defining fallbacks
*/
html10n.localize = function(langs) {
- var that = this,
- candidates = [];
- // if a single string, bundle it as an array:
- if ('string' == typeof langs) {
- langs = [langs];
- }
+ var that = this
+ // if only one string => create an array
+ if ('string' == typeof langs) langs = [langs]
- // Determine candidates from langs:
- // - Omitting empty strings
- // - Adding in non-qualified versions of country-qualified codes.
+ // Expand two-part locale specs
+ var i=0
langs.forEach(function(lang) {
- var splat;
- if(!lang) { return; }
- (candidates.indexOf(lang) == -1) && candidates.push(lang);
- splat = lang.split('-');
- if (splat[1]) {
- (candidates.indexOf(splat[0]) == -1) && candidates.push(splat[0]);
- }
- });
-
- // Append script fallbacks for region-specific locales if applicable
- for (var lang in html10n.scripts) {
- i = candidates.indexOf(lang);
- if (~i) candidates.splice(i, 0, html10n.scripts[lang])
- }
+ if(!lang) return;
+ langs[i++] = lang;
+ if(~lang.indexOf('-')) langs[i++] = lang.substr(0, lang.indexOf('-'));
+ })
- this.build(candidates, function(er, translations) {
+ this.build(langs, function(er, translations) {
html10n.translations = translations
html10n.translateElement(translations)
that.trigger('localized')
@@ -752,18 +710,18 @@ window.html10n = (function(window, document, undefined) {
// translate element itself if necessary
this.translateNode(translations, element)
}
-
+
function asyncForEach(list, iterator, cb) {
var i = 0
, n = list.length
iterator(list[i], i, function each(err) {
- if(err) consoleLog(err)
+ if(err) console.error(err)
i++
if (i < n) return iterator(list[i],i, each);
cb()
})
}
-
+
function getTranslatableChildren(element) {
if(!document.querySelectorAll) {
if (!element) return []
@@ -777,62 +735,55 @@ window.html10n = (function(window, document, undefined) {
}
return element.querySelectorAll('*[data-l10n-id]')
}
-
+
html10n.get = function(id, args) {
var translations = html10n.translations
- if(!translations) {
- if (! html10n.quiet) {
- consoleWarn('No translations available (yet)');
- }
- return;
- }
- if(!translations[id]) return consoleWarn('Could not find string '+id)
-
+ if(!translations) return console.warn('No translations available (yet)')
+ if(!translations[id]) return console.warn('Could not find string '+id)
+
// apply macros
var str = translations[id]
-
+
str = substMacros(id, str, args)
-
+
// apply args
str = substArguments(str, args)
-
+
return str
}
-
+
// replace {{arguments}} with their values or the
// associated translation string (based on its key)
function substArguments(str, args) {
- var reArgs = /\{\{\s*([a-zA-Z_\-\.]+)\s*\}\}/,
- translations = html10n.translations,
- match;
-
+ var reArgs = /\{\{\s*([a-zA-Z\.]+)\s*\}\}/
+ , match
+
while (match = reArgs.exec(str)) {
if (!match || match.length < 2)
return str // argument key not found
var arg = match[1]
, sub = ''
- if (args && (arg in args)) {
+ if (arg in args) {
sub = args[arg]
} else if (arg in translations) {
sub = translations[arg]
} else {
- consoleWarn('Could not satisfy argument {{' + arg + '}}' +
- ' for string "' + str + '"');
+ console.warn('Could not find argument {{' + arg + '}}')
return str
}
str = str.substring(0, match.index) + sub + str.substr(match.index + match[0].length)
}
-
+
return str
}
-
+
// replace {[macros]} with their values
function substMacros(key, str, args) {
- var regex = /\{\[\s*([a-zA-Z]+)\(([a-zA-Z]+)\)((\s*([a-zA-Z]+)\: ?([^,]+?),?)+)*\s*\]\}/ //.exec('{{n}} {[plural(n) one: Bomba, other: Bombe]} ]}')
+ var regex = /\{\[\s*([a-zA-Z]+)\(([a-zA-Z]+)\)((\s*([a-zA-Z]+)\: ?([ a-zA-Z{}]+),?)+)*\s*\]\}/ //.exec('{[ plural(n) other: are {{n}}, one: is ]}')
, match
-
+
while(match = regex.exec(str)) {
// a macro has been found
// Note: at the moment, only one parameter is supported
@@ -840,18 +791,18 @@ window.html10n = (function(window, document, undefined) {
, paramName = match[2]
, optv = match[3]
, opts = {}
-
+
if (!(macroName in html10n.macros)) continue
-
+
if(optv) {
- optv.match(/(?=\s*)([a-zA-Z]+)\: ?([^,\]]+)(?=,?)/g).forEach(function(arg) {
+ optv.match(/(?=\s*)([a-zA-Z]+)\: ?([ a-zA-Z{}]+)(?=,?)/g).forEach(function(arg) {
var parts = arg.split(':')
, name = parts[0]
, value = parts[1].trim()
opts[name] = value
})
}
-
+
var param
if (args && paramName in args) {
param = args[paramName]
@@ -863,10 +814,10 @@ window.html10n = (function(window, document, undefined) {
var macro = html10n.macros[macroName]
str = str.substr(0, match.index) + macro(key, param, opts) + str.substr(match.index+match[0].length)
}
-
+
return str
}
-
+
/**
* Applies translations to a DOM node (recursive)
*/
@@ -877,21 +828,21 @@ window.html10n = (function(window, document, undefined) {
str.id = node.getAttribute('data-l10n-id')
if (!str.id) return
- if(!translations[str.id]) return consoleWarn('Couldn\'t find translation key '+str.id)
+ if(!translations[str.id]) return console.warn('Couldn\'t find translation key '+str.id)
// get args
if(window.JSON) {
- str.args = node.getAttribute('data-l10n-args') ? JSON.parse(node.getAttribute('data-l10n-args')) : [];
+ str.args = JSON.parse(node.getAttribute('data-l10n-args'))
}else{
try{
str.args = eval(node.getAttribute('data-l10n-args'))
}catch(e) {
- consoleWarn('Couldn\'t parse args for '+str.id)
+ console.warn('Couldn\'t parse args for '+str.id)
}
}
-
+
str.str = html10n.get(str.id, str.args)
-
+
// get attribute name to apply str to
var prop
, index = str.id.lastIndexOf('.')
@@ -900,7 +851,6 @@ window.html10n = (function(window, document, undefined) {
, "innerHTML": 1
, "alt": 1
, "textContent": 1
- , "placeholder": 1
, "value": 1
}
if (index > 0 && str.id.substr(index + 1) in attrList) { // an attribute has been specified
@@ -912,6 +862,9 @@ window.html10n = (function(window, document, undefined) {
// Apply translation
if (node.children.length === 0 || prop != 'textContent') {
node[prop] = str.str
+ node.setAttribute("aria-label", str.str); // Sets the aria-label
+ // The idea of the above is that we always have an aria value
+ // This might be a bit of an abrupt solution but let's see how it goes
} else {
var children = node.childNodes,
found = false
@@ -926,11 +879,11 @@ window.html10n = (function(window, document, undefined) {
}
}
if (!found) {
- consoleWarn('Unexpected error: could not translate element content for key '+str.id, node)
+ console.warn('Unexpected error: could not translate element content for key '+str.id, node)
}
}
}
-
+
/**
* Builds a translation object from a list of langs (loads the necessary translations)
* @param langs Array - a list of langs sorted by priority (default langs should go last)
@@ -945,11 +898,11 @@ window.html10n = (function(window, document, undefined) {
}, function() {
var lang
langs.reverse()
-
+
// loop through the priority array...
for (var i=0, n=langs.length; i < n; i++) {
lang = langs[i]
-
+
if(!lang) continue;
if(!(lang in that.loader.langs)) {// uh, we don't have this lang availbable..
// then check for related langs
@@ -962,13 +915,13 @@ window.html10n = (function(window, document, undefined) {
}
if(lang != l) continue;
}
-
+
// ... and apply all strings of the current lang in the list
// to our build object
for (var string in that.loader.langs[lang]) {
build[string] = that.loader.langs[lang][string]
}
-
+
// the last applied lang will be exposed as the
// lang the page was translated to
that.language = lang
@@ -976,7 +929,7 @@ window.html10n = (function(window, document, undefined) {
cb(null, build)
})
}
-
+
/**
* Returns the language that was last applied to the translations hash
* thus overriding most of the formerly applied langs
@@ -1009,7 +962,7 @@ window.html10n = (function(window, document, undefined) {
this.loader = new Loader(resources)
this.trigger('indexed')
}
-
+
if (document.addEventListener) // modern browsers and IE9+
document.addEventListener('DOMContentLoaded', function() {
html10n.index()