Missing webL10n library files
This commit is contained in:
parent
9b8b3bd25f
commit
7859ba89c3
3
external/webL10n/README.md
vendored
Normal file
3
external/webL10n/README.md
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
The source code for the library can be found at
|
||||
|
||||
https://github.com/fabi1cazenave/webL10n
|
304
external/webL10n/l10n.js
vendored
Normal file
304
external/webL10n/l10n.js
vendored
Normal file
@ -0,0 +1,304 @@
|
||||
/* Copyright (c) 2011-2012 Fabien Cazenave, Mozilla.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
(function(window) {
|
||||
var gL10nData = {};
|
||||
var gTextData = '';
|
||||
var gLanguage = '';
|
||||
|
||||
// parser
|
||||
|
||||
function evalString(text) {
|
||||
return text.replace(/\\\\/g, '\\')
|
||||
.replace(/\\n/g, '\n')
|
||||
.replace(/\\r/g, '\r')
|
||||
.replace(/\\t/g, '\t')
|
||||
.replace(/\\b/g, '\b')
|
||||
.replace(/\\f/g, '\f')
|
||||
.replace(/\\{/g, '{')
|
||||
.replace(/\\}/g, '}')
|
||||
.replace(/\\"/g, '"')
|
||||
.replace(/\\'/g, "'");
|
||||
}
|
||||
|
||||
function parseProperties(text, lang) {
|
||||
var reBlank = /^\s*|\s*$/;
|
||||
var reComment = /^\s*#|^\s*$/;
|
||||
var reSection = /^\s*\[(.*)\]\s*$/;
|
||||
var reImport = /^\s*@import\s+url\((.*)\)\s*$/i;
|
||||
|
||||
// parse the *.properties file into an associative array
|
||||
var currentLang = '*';
|
||||
var supportedLang = [];
|
||||
var skipLang = false;
|
||||
var data = [];
|
||||
var match = '';
|
||||
var entries = text.replace(reBlank, '').split(/[\r\n]+/);
|
||||
for (var i = 0; i < entries.length; i++) {
|
||||
var line = entries[i];
|
||||
|
||||
// comment or blank line?
|
||||
if (reComment.test(line))
|
||||
continue;
|
||||
|
||||
// section start?
|
||||
if (reSection.test(line)) {
|
||||
match = reSection.exec(line);
|
||||
currentLang = match[1];
|
||||
skipLang = (currentLang != lang) && (currentLang != '*');
|
||||
continue;
|
||||
} else if (skipLang) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// @import rule?
|
||||
if (reImport.test(line)) {
|
||||
match = reImport.exec(line);
|
||||
}
|
||||
|
||||
// key-value pair
|
||||
var tmp = line.split('=');
|
||||
if (tmp.length > 1)
|
||||
data[tmp[0]] = evalString(tmp[1]);
|
||||
}
|
||||
|
||||
// find the attribute descriptions, if any
|
||||
for (var key in data) {
|
||||
var id, prop, index = key.lastIndexOf('.');
|
||||
if (index > 0) { // attribute
|
||||
id = key.substring(0, index);
|
||||
prop = key.substr(index + 1);
|
||||
} else { // textContent, could be innerHTML as well
|
||||
id = key;
|
||||
prop = 'textContent';
|
||||
}
|
||||
if (!gL10nData[id])
|
||||
gL10nData[id] = {};
|
||||
gL10nData[id][prop] = data[key];
|
||||
}
|
||||
}
|
||||
|
||||
function parse(text, lang) {
|
||||
gTextData += text;
|
||||
// we only support *.properties files at the moment
|
||||
return parseProperties(text, lang);
|
||||
}
|
||||
|
||||
// load and parse the specified resource file
|
||||
function loadResource(href, lang, onSuccess, onFailure) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', href, true);
|
||||
xhr.overrideMimeType('text/plain; charset=utf-8');
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState == 4) {
|
||||
if (xhr.status == 200 || xhr.status == 0) {
|
||||
parse(xhr.responseText, lang);
|
||||
if (onSuccess)
|
||||
onSuccess();
|
||||
} else {
|
||||
if (onFailure)
|
||||
onFailure();
|
||||
}
|
||||
}
|
||||
};
|
||||
xhr.send(null);
|
||||
}
|
||||
|
||||
// load and parse all resources for the specified locale
|
||||
function loadLocale(lang, callback) {
|
||||
clear();
|
||||
|
||||
// check all <link type="application/l10n" href="..." /> nodes
|
||||
// and load the resource files
|
||||
var langLinks = document.querySelectorAll('link[type="application/l10n"]');
|
||||
var langCount = langLinks.length;
|
||||
|
||||
// start the callback when all resources are loaded
|
||||
var onResourceLoaded = null;
|
||||
var gResourceCount = 0;
|
||||
onResourceLoaded = function() {
|
||||
gResourceCount++;
|
||||
if (gResourceCount >= langCount) {
|
||||
// execute the [optional] callback
|
||||
if (callback)
|
||||
callback();
|
||||
// fire a 'localized' DOM event
|
||||
var evtObject = document.createEvent('Event');
|
||||
evtObject.initEvent('localized', false, false);
|
||||
evtObject.language = lang;
|
||||
window.dispatchEvent(evtObject);
|
||||
}
|
||||
}
|
||||
|
||||
// load all resource files
|
||||
function l10nResourceLink(link) {
|
||||
var href = link.href;
|
||||
var type = link.type;
|
||||
this.load = function(lang, callback) {
|
||||
var applied = lang;
|
||||
loadResource(href, lang, callback, function() {
|
||||
console.warn(href + ' not found.');
|
||||
applied = '';
|
||||
});
|
||||
return applied; // return lang if found, an empty string if not found
|
||||
};
|
||||
}
|
||||
|
||||
gLanguage = lang;
|
||||
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
|
||||
gLanguage = '';
|
||||
}
|
||||
}
|
||||
|
||||
// fetch an l10n object, warn if not found
|
||||
function getL10nData(key) {
|
||||
var data = gL10nData[key];
|
||||
if (!data)
|
||||
console.warn('[l10n] #' + key + ' missing for [' + gLanguage + ']');
|
||||
return data;
|
||||
}
|
||||
|
||||
// replace {{arguments}} with their values
|
||||
function substArguments(str, args) {
|
||||
var reArgs = /\{\{\s*([a-zA-Z\.]+)\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 = '';
|
||||
if (arg in args) {
|
||||
sub = args[arg];
|
||||
} else if (arg in gL10nData) {
|
||||
sub = gL10nData[arg].textContent;
|
||||
} else {
|
||||
console.warn('[l10n] could not find argument {{' + arg + '}}');
|
||||
return str;
|
||||
}
|
||||
|
||||
str = str.substring(0, match.index) + sub +
|
||||
str.substr(match.index + match[0].length);
|
||||
match = reArgs.exec(str);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
// translate a string
|
||||
function translateString(key, args) {
|
||||
var data = getL10nData(key);
|
||||
if (!data)
|
||||
return '{{' + key + '}}';
|
||||
return substArguments(data.textContent, args);
|
||||
}
|
||||
|
||||
// translate an HTML element
|
||||
function translateElement(element) {
|
||||
if (!element || !element.dataset)
|
||||
return;
|
||||
|
||||
// get the related l10n object
|
||||
var key = element.dataset.l10nId;
|
||||
var data = getL10nData(key);
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
// get arguments (if any)
|
||||
// TODO: more flexible parser?
|
||||
var args;
|
||||
if (element.dataset.l10nArgs) try {
|
||||
args = JSON.parse(element.dataset.l10nArgs);
|
||||
} catch (e) {
|
||||
console.warn('[l10n] could not parse arguments for #' + key + '');
|
||||
}
|
||||
|
||||
// translate element
|
||||
// TODO: security check?
|
||||
for (var k in data)
|
||||
element[k] = substArguments(data[k], args);
|
||||
}
|
||||
|
||||
// translate an HTML subtree
|
||||
function translateFragment(element) {
|
||||
element = element || document.querySelector('html');
|
||||
|
||||
// check all translatable children (= w/ a `data-l10n-id' attribute)
|
||||
var children = element.querySelectorAll('*[data-l10n-id]');
|
||||
var elementCount = children.length;
|
||||
for (var i = 0; i < elementCount; i++)
|
||||
translateElement(children[i]);
|
||||
|
||||
// translate element itself if necessary
|
||||
if (element.dataset.l10nId)
|
||||
translateElement(element);
|
||||
}
|
||||
|
||||
// clear all l10n data
|
||||
function clear() {
|
||||
gL10nData = {};
|
||||
gTextData = '';
|
||||
gLanguage = '';
|
||||
}
|
||||
|
||||
// load the default locale on startup
|
||||
window.addEventListener('DOMContentLoaded', function() {
|
||||
var lang = navigator.language;
|
||||
if (navigator.mozSettings) {
|
||||
var req = navigator.mozSettings.getLock().get('language.current');
|
||||
req.onsuccess = function() {
|
||||
loadLocale(req.result['language.current'] || lang, translateFragment);
|
||||
};
|
||||
req.onerror = function() {
|
||||
loadLocale(lang, translateFragment);
|
||||
};
|
||||
} else {
|
||||
loadLocale(lang, translateFragment);
|
||||
}
|
||||
});
|
||||
|
||||
// Public API
|
||||
document.mozL10n = {
|
||||
// get a localized string
|
||||
get: translateString,
|
||||
|
||||
// get|set the document language and direction
|
||||
get language() {
|
||||
return {
|
||||
// get|set the document language (ISO-639-1)
|
||||
get code() { return gLanguage; },
|
||||
set code(lang) { loadLocale(lang, translateFragment); },
|
||||
|
||||
// get the direction (ltr|rtl) of the current language
|
||||
get direction() {
|
||||
// http://www.w3.org/International/questions/qa-scripts
|
||||
// Arabic, Hebrew, Farsi, Pashto, Urdu
|
||||
var rtlList = ['ar', 'he', 'fa', 'ps', 'ur'];
|
||||
return (rtlList.indexOf(gLanguage) >= 0) ? 'rtl' : 'ltr';
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
})(this);
|
Loading…
x
Reference in New Issue
Block a user