7d2f736084
When we fail to download the localizaion javascript file, for whatever reason, we end up failing to load the document. This is far from ideal. Instead, we simply log the error and move on. The end result in such a failure scenario is that the document loads, but the UI is only available in English. Change-Id: I5d29ff68870d0cd84d86658ccfd4e3185cc62562 Signed-off-by: Ashod Nakashian <ashod.nakashian@collabora.co.uk>
290 lines
7.9 KiB
JavaScript
290 lines
7.9 KiB
JavaScript
/*
|
|
* l10n.js
|
|
* 2016-05-17
|
|
*
|
|
* By Eli Grey, http://eligrey.com
|
|
* Licensed under the MIT License
|
|
* See https://github.com/eligrey/l10n.js/blob/master/LICENSE.md
|
|
*/
|
|
|
|
/*global XMLHttpRequest, setTimeout, document, navigator, ActiveXObject*/
|
|
|
|
/*! @source http://purl.eligrey.com/github/l10n.js/blob/master/l10n.js*/
|
|
|
|
(function () {
|
|
"use strict";
|
|
|
|
var
|
|
undef_type = "undefined"
|
|
, string_type = "string"
|
|
, nav = {}
|
|
, String_ctr = String
|
|
, has_own_prop = Object.prototype.hasOwnProperty
|
|
, load_queues = {}
|
|
, localizations = {}
|
|
, FALSE = !1
|
|
, TRUE = !0
|
|
, browserless = FALSE
|
|
// the official format is application/vnd.oftn.l10n+json, though l10n.js will also
|
|
// accept application/x-l10n+json and application/l10n+json
|
|
, l10n_js_media_type = /^\s*application\/(?:vnd\.oftn\.|x-)?l10n\+json\s*(?:$|;)/i
|
|
, XHR
|
|
|
|
// property minification aids
|
|
, $locale = "locale"
|
|
, $default_locale = "defaultLocale"
|
|
, $to_locale_string = "toLocaleString"
|
|
, $to_lowercase = "toLowerCase"
|
|
|
|
, array_index_of = Array.prototype.indexOf || function (item) {
|
|
var
|
|
len = this.length
|
|
, i = 0
|
|
;
|
|
|
|
for (; i < len; i++) {
|
|
if (i in this && this[i] === item) {
|
|
return i;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
, request_JSON = function (uri) {
|
|
if(browserless)
|
|
return loadFromDisk(uri);
|
|
|
|
var req = new XHR(),
|
|
data = {};
|
|
|
|
try {
|
|
// sadly, this has to be blocking to allow for a graceful degrading API
|
|
req.open("GET", uri, FALSE);
|
|
req.send(null);
|
|
} catch (e) {
|
|
console.log('Localization Error: Unable to get localization data: ' + uri, e);
|
|
}
|
|
|
|
// Status codes can be inconsistent across browsers so we simply try to parse
|
|
// the response text and catch any errors. This deals with failed requests as
|
|
// well as malformed json files.
|
|
try {
|
|
data = JSON.parse(req.responseText);
|
|
} catch(e) {
|
|
// warn about error without stopping execution
|
|
setTimeout(function () {
|
|
// Error messages are not localized as not to cause an infinite loop
|
|
var l10n_err = new Error("Unable to load localization data: " + uri);
|
|
l10n_err.name = "Localization Error";
|
|
throw l10n_err;
|
|
}, 0);
|
|
}
|
|
|
|
return data;
|
|
}
|
|
, load = String_ctr[$to_locale_string] = function (data) {
|
|
// don't handle function.toLocaleString(indentationAmount:Number)
|
|
if (arguments.length > 0 && typeof data !== "number") {
|
|
if (typeof data === string_type) {
|
|
load(request_JSON(data));
|
|
} else if (data === FALSE) {
|
|
// reset all localizations
|
|
localizations = {};
|
|
} else {
|
|
// Extend current localizations instead of completely overwriting them
|
|
var locale, localization, message;
|
|
for (locale in data) {
|
|
if (has_own_prop.call(data, locale)) {
|
|
localization = data[locale];
|
|
locale = locale[$to_lowercase]();
|
|
|
|
if (!(locale in localizations) || localization === FALSE) {
|
|
// reset locale if not existing or reset flag is specified
|
|
localizations[locale] = {};
|
|
}
|
|
|
|
if (localization === FALSE) {
|
|
continue;
|
|
}
|
|
|
|
// URL specified
|
|
if (typeof localization === string_type) {
|
|
if (String_ctr[$locale][$to_lowercase]().indexOf(locale) === 0) {
|
|
localization = request_JSON(localization);
|
|
} else {
|
|
// queue loading locale if not needed
|
|
if (!(locale in load_queues)) {
|
|
load_queues[locale] = [];
|
|
}
|
|
load_queues[locale].push(localization);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
for (message in localization) {
|
|
if (has_own_prop.call(localization, message)) {
|
|
localizations[locale][message] = localization[message];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Return what function.toLocaleString() normally returns
|
|
return Function.prototype[$to_locale_string].apply(String_ctr, arguments);
|
|
}
|
|
, loadFromDisk = String_ctr[$to_locale_string] = function (uri) {
|
|
var fs = require('fs');
|
|
var read = fs.readFileSync(uri, 'utf8');
|
|
return JSON.parse(read);
|
|
}
|
|
, process_load_queue = function (locale) {
|
|
var
|
|
queue = load_queues[locale]
|
|
, i = 0
|
|
, len = queue.length
|
|
, localization
|
|
;
|
|
|
|
for (; i < len; i++) {
|
|
localization = {};
|
|
localization[locale] = request_JSON(queue[i]);
|
|
load(localization);
|
|
}
|
|
|
|
delete load_queues[locale];
|
|
}
|
|
, use_default
|
|
, localize = String_ctr.prototype[$to_locale_string] = function () {
|
|
var
|
|
using_default = use_default
|
|
, current_locale = String_ctr[using_default ? $default_locale : $locale]
|
|
, parts = current_locale[$to_lowercase]().split("-")
|
|
, i = parts.length
|
|
, this_val = this.valueOf()
|
|
, locale
|
|
;
|
|
|
|
use_default = FALSE;
|
|
|
|
// Iterate through locales starting at most-specific until a localization is found
|
|
do {
|
|
locale = parts.slice(0, i).join("-");
|
|
// load locale if not loaded
|
|
if (locale in load_queues) {
|
|
process_load_queue(locale);
|
|
}
|
|
if (locale in localizations && this_val in localizations[locale]) {
|
|
return localizations[locale][this_val];
|
|
}
|
|
}
|
|
while (i--);
|
|
|
|
if (!using_default && String_ctr[$default_locale]) {
|
|
use_default = TRUE;
|
|
return localize.call(this_val);
|
|
}
|
|
|
|
return this_val;
|
|
}
|
|
;
|
|
|
|
try
|
|
{
|
|
nav = self.navigator;
|
|
}
|
|
catch(selfNotFoundException)
|
|
{
|
|
if(global.nav)
|
|
{
|
|
nav = global.nav;
|
|
}
|
|
else
|
|
{
|
|
var nodeError = "Problem setting nav in L10N. You are most likely running in a non-browser environment like Node." +
|
|
"If this is the case, you can resolve this error by setting global.nav to an object which contains a \"language\" field. ";
|
|
throw new Error(nodeError);
|
|
}
|
|
browserless = TRUE;
|
|
}
|
|
|
|
if (!browserless && typeof XMLHttpRequest === undef_type && typeof ActiveXObject !== undef_type) {
|
|
var AXO = ActiveXObject;
|
|
|
|
XHR = function () {
|
|
try {
|
|
return new AXO("Msxml2.XMLHTTP.6.0");
|
|
} catch (xhrEx1) {}
|
|
try {
|
|
return new AXO("Msxml2.XMLHTTP.3.0");
|
|
} catch (xhrEx2) {}
|
|
try {
|
|
return new AXO("Msxml2.XMLHTTP");
|
|
} catch (xhrEx3) {}
|
|
|
|
throw new Error("XMLHttpRequest not supported by this browser.");
|
|
};
|
|
} else {
|
|
try
|
|
{
|
|
XHR = XMLHttpRequest;
|
|
}
|
|
catch(xhrEx4)
|
|
{
|
|
if(global.XMLHttpRequest) {
|
|
XHR = global.XMLHttpRequest;
|
|
}
|
|
else {
|
|
var nodeError = "Problem setting XHR in L10N. You are most likely running in a non-browser environment like Node." +
|
|
"If this is the case, you can resolve this error by setting global.XMLHttpRequest to a function which produces XMLHttpRequests. " +
|
|
"\nTip: if you are using node, you might want to use the XHR2 package (usage: global.XMLHttpRequest = require('xhr2')";
|
|
throw new Error(nodeError);
|
|
}
|
|
}
|
|
}
|
|
|
|
String_ctr[$default_locale] = String_ctr[$default_locale] || "";
|
|
var lang = nav && (nav.language || nav.userLanguage) || "";
|
|
String_ctr[$locale] = lang;
|
|
document.documentElement.lang = lang;
|
|
|
|
if (!browserless || typeof document !== undef_type) {
|
|
var
|
|
elts = document.getElementsByTagName("link")
|
|
, i = elts.length
|
|
, localization
|
|
;
|
|
|
|
while (i--) {
|
|
var
|
|
elt = elts[i]
|
|
, rel = (elt.getAttribute("rel") || "")[$to_lowercase]().split(/\s+/)
|
|
;
|
|
|
|
if (l10n_js_media_type.test(elt.type)) {
|
|
if (array_index_of.call(rel, "localizations") !== -1) {
|
|
// multiple localizations
|
|
load(elt.getAttribute("href"));
|
|
} else if (array_index_of.call(rel, "localization") !== -1) {
|
|
// single localization
|
|
localization = {};
|
|
localization[(elt.getAttribute("hreflang") || "")[$to_lowercase]()] =
|
|
elt.getAttribute("href");
|
|
load(localization);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(global.l10NLocalFilePath) {
|
|
load(global.l10NLocalFilePath);
|
|
}
|
|
else {
|
|
var nodeError = "Problem loading localization file. You are most likely running in a non-browser environment like Node." +
|
|
"If this is the case, you can resolve this error by setting global.l10NLocalFilePath to the path of your localization file. ";
|
|
throw new Error(nodeError);
|
|
}
|
|
}
|
|
|
|
}());
|