Skip to content

Commit 4f77b36

Browse files
committed
Added a default locale feature and normalized code style
This feature is useful for people using l10n.js in a non-passive manner.
1 parent 1689ad1 commit 4f77b36

File tree

2 files changed

+185
-170
lines changed

2 files changed

+185
-170
lines changed

l10n.js

Lines changed: 183 additions & 168 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* l10n.js
3-
* 2011-05-12
3+
* 2013-04-18
44
*
55
* By Eli Grey, http://eligrey.com
66
* Licensed under the X11/MIT License
@@ -11,201 +11,216 @@
1111

1212
/*! @source http://purl.eligrey.com/github/l10n.js/blob/master/l10n.js*/
1313

14+
(function () {
1415
"use strict";
1516

16-
(function () {
17+
var
18+
undef_type = "undefined"
19+
, string_type = "string"
20+
, nav = self.navigator
21+
, String_ctr = String
22+
, has_own_prop = Object.prototype.hasOwnProperty
23+
, load_queues = {}
24+
, localizations = {}
25+
, FALSE = !1
26+
, TRUE = !0
27+
// the official format is application/vnd.oftn.l10n+json, though l10n.js will also
28+
// accept application/x-l10n+json and application/l10n+json
29+
, l10n_js_media_type = /^\s*application\/(?:vnd\.oftn\.|x-)?l10n\+json\s*(?:$|;)/i
30+
, XHR
31+
32+
// property minification aids
33+
, $locale = "locale"
34+
, $default_locale = "defaultLocale"
35+
, $to_locale_string = "toLocaleString"
36+
, $to_lowercase = "toLowerCase"
37+
38+
, array_index_of = Array.prototype.indexOf || function (item) {
1739
var
18-
undef_type = "undefined"
19-
, string_type = "string"
20-
, String_ctr = String
21-
, has_own_prop = Object.prototype.hasOwnProperty
22-
, load_queues = {}
23-
, localizations = {}
24-
, FALSE = !1
25-
// the official format is application/vnd.oftn.l10n+json, though l10n.js will also
26-
// accept application/x-l10n+json and application/l10n+json
27-
, l10n_js_media_type = /^\s*application\/(?:vnd\.oftn\.|x-)?l10n\+json\s*(?:$|;)/i
28-
, XHR
29-
, $to_locale_string = "toLocaleString"
30-
, $to_lowercase = "toLowerCase"
40+
len = this.length
41+
, i = 0
42+
;
3143

32-
, array_index_of = Array.prototype.indexOf || function (item) {
33-
var
34-
len = this.length
35-
, i = 0
36-
;
37-
38-
for (; i < len; i++) {
39-
if (i in this && this[i] === item) {
40-
return i;
41-
}
44+
for (; i < len; i++) {
45+
if (i in this && this[i] === item) {
46+
return i;
4247
}
43-
44-
return -1;
4548
}
46-
, request_JSON = function (uri) {
47-
var req = new XHR();
48-
49-
// sadly, this has to be blocking to allow for a graceful degrading API
50-
req.open("GET", uri, FALSE);
51-
req.send(null);
49+
50+
return -1;
51+
}
52+
, request_JSON = function (uri) {
53+
var req = new XHR();
54+
55+
// sadly, this has to be blocking to allow for a graceful degrading API
56+
req.open("GET", uri, FALSE);
57+
req.send(null);
58+
59+
if (req.status !== 200) {
60+
// warn about error without stopping execution
61+
setTimeout(function () {
62+
// Error messages are not localized as not to cause an infinite loop
63+
var l10n_err = new Error("Unable to load localization data: " + uri);
64+
l10n_err.name = "Localization Error";
65+
throw l10n_err;
66+
}, 0);
5267

53-
if (req.status !== 200) {
54-
// warn about error without stopping execution
55-
setTimeout(function () {
56-
// Error messages are not localized as not to cause an infinite loop
57-
var l10n_err = new Error("Unable to load localization data: " + uri);
58-
l10n_err.name = "Localization Error";
59-
throw l10n_err;
60-
}, 0);
61-
62-
return {};
63-
} else {
64-
return JSON.parse(req.responseText);
65-
}
68+
return {};
69+
} else {
70+
return JSON.parse(req.responseText);
6671
}
67-
, load = String_ctr[$to_locale_string] = function (data) {
68-
// don't handle function[$to_locale_string](indentationAmount:Number)
69-
if (arguments.length > 0 && typeof data !== "number") {
70-
if (typeof data === string_type) {
71-
load(request_JSON(data));
72-
} else if (data === FALSE) {
73-
// reset all localizations
74-
localizations = {};
75-
} else {
76-
// Extend current localizations instead of completely overwriting them
77-
for (var locale in data) {
78-
if (has_own_prop.call(data, locale)) {
79-
var localization = data[locale];
80-
locale = locale[$to_lowercase]();
81-
82-
if (!(locale in localizations) || localization === FALSE) {
83-
// reset locale if not existing or reset flag is specified
84-
localizations[locale] = {};
85-
}
86-
87-
if (localization === FALSE) {
88-
continue;
89-
}
90-
91-
// URL specified
92-
if (typeof localization === string_type) {
93-
if (String_ctr.locale[$to_lowercase]().indexOf(locale) === 0) {
94-
localization = request_JSON(localization);
95-
} else {
96-
// queue loading locale if not needed
97-
if (!(locale in load_queues)) {
98-
load_queues[locale] = [];
99-
}
100-
load_queues[locale].push(localization);
101-
continue;
72+
}
73+
, load = String_ctr[$to_locale_string] = function (data) {
74+
// don't handle function[$to_locale_string](indentationAmount:Number)
75+
if (arguments.length > 0 && typeof data !== "number") {
76+
if (typeof data === string_type) {
77+
load(request_JSON(data));
78+
} else if (data === FALSE) {
79+
// reset all localizations
80+
localizations = {};
81+
} else {
82+
// Extend current localizations instead of completely overwriting them
83+
var locale, localization, message;
84+
for (locale in data) {
85+
if (has_own_prop.call(data, locale)) {
86+
localization = data[locale];
87+
locale = locale[$to_lowercase]();
88+
89+
if (!(locale in localizations) || localization === FALSE) {
90+
// reset locale if not existing or reset flag is specified
91+
localizations[locale] = {};
92+
}
93+
94+
if (localization === FALSE) {
95+
continue;
96+
}
97+
98+
// URL specified
99+
if (typeof localization === string_type) {
100+
if (String_ctr[$locale][$to_lowercase]().indexOf(locale) === 0) {
101+
localization = request_JSON(localization);
102+
} else {
103+
// queue loading locale if not needed
104+
if (!(locale in load_queues)) {
105+
load_queues[locale] = [];
102106
}
107+
load_queues[locale].push(localization);
108+
continue;
103109
}
104-
105-
for (var message in localization) {
106-
if (has_own_prop.call(localization, message)) {
107-
localizations[locale][message] = localization[message];
108-
}
110+
}
111+
112+
for (message in localization) {
113+
if (has_own_prop.call(localization, message)) {
114+
localizations[locale][message] = localization[message];
109115
}
110116
}
111117
}
112118
}
113119
}
114-
// Return what function[$to_locale_string]() normally returns
115-
return Function.prototype[$to_locale_string].apply(String_ctr, arguments);
116120
}
117-
, process_load_queue = function (locale) {
118-
var queue = load_queues[locale],
119-
i = 0,
120-
len = queue.length;
121-
122-
for (; i < len; i++) {
123-
var localization = {};
124-
localization[locale] = request_JSON(queue[i]);
125-
load(localization);
126-
}
127-
128-
delete load_queues[locale];
129-
}
130-
121+
// Return what function[$to_locale_string]() normally returns
122+
return Function.prototype[$to_locale_string].apply(String_ctr, arguments);
123+
}
124+
, process_load_queue = function (locale) {
125+
var
126+
queue = load_queues[locale]
127+
, i = 0
128+
, len = queue.length
129+
, localization
131130
;
132131

133-
if (typeof XMLHttpRequest === undef_type && typeof ActiveXObject !== undef_type) {
134-
var AXO = ActiveXObject;
135-
136-
XHR = function () {
137-
try {
138-
return new AXO("Msxml2.XMLHTTP.6.0");
139-
} catch (xhrEx1) {}
140-
try {
141-
return new AXO("Msxml2.XMLHTTP.3.0");
142-
} catch (xhrEx2) {}
143-
try {
144-
return new AXO("Msxml2.XMLHTTP");
145-
} catch (xhrEx3) {}
146-
147-
throw new Error("XMLHttpRequest not supported by this browser.");
148-
};
149-
} else {
150-
XHR = XMLHttpRequest;
132+
for (; i < len; i++) {
133+
localization = {};
134+
localization[locale] = request_JSON(queue[i]);
135+
load(localization);
151136
}
152137

153-
if (!String_ctr.locale) {
154-
if (typeof navigator !== undef_type) {
155-
var nav = navigator;
156-
String_ctr.locale = nav.language || nav.userLanguage || "";
157-
} else {
158-
String_ctr.locale = "";
138+
delete load_queues[locale];
139+
}
140+
, use_default
141+
, localize = String_ctr.prototype[$to_locale_string] = function () {
142+
var
143+
using_default = use_default
144+
, current_locale = String_ctr[using_default ? $default_locale : $locale]
145+
, parts = current_locale[$to_lowercase]().split("-")
146+
, i = parts.length
147+
, this_val = this.valueOf()
148+
, locale
149+
;
150+
151+
use_default = FALSE;
152+
153+
// Iterate through locales starting at most-specific until a localization is found
154+
do {
155+
locale = parts.slice(0, i).join("-");
156+
// load locale if not loaded
157+
if (locale in load_queues) {
158+
process_load_queue(locale);
159+
}
160+
if (locale in localizations && this_val in localizations[locale]) {
161+
return localizations[locale][this_val];
159162
}
160163
}
164+
while (i --> 1);
161165

162-
if (typeof document !== undef_type) {
163-
var
164-
elts = document.getElementsByTagName("link")
165-
, i = elts.length
166-
;
167-
168-
while (i--) {
169-
var
170-
elt = elts[i]
171-
, rel = (elt.getAttribute("rel") || "")[$to_lowercase]().split(/\s+/)
172-
;
173-
174-
if (l10n_js_media_type.test(elt.type)) {
175-
if (array_index_of.call(rel, "localizations") !== -1) {
176-
// multiple localizations
177-
load(elt.getAttribute("href"));
178-
} else if (array_index_of.call(rel, "localization") !== -1) {
179-
// single localization
180-
var localization = {};
181-
localization[(elt.getAttribute("hreflang") || "")[$to_lowercase]()] =
182-
elt.getAttribute("href");
183-
load(localization);
184-
}
185-
}
186-
}
166+
if (!using_default && String_ctr[$default_locale]) {
167+
use_default = TRUE;
168+
return localize.call(this_val);
187169
}
170+
171+
return this_val;
172+
}
173+
;
174+
175+
if (typeof XMLHttpRequest === undef_type && typeof ActiveXObject !== undef_type) {
176+
var AXO = ActiveXObject;
177+
178+
XHR = function () {
179+
try {
180+
return new AXO("Msxml2.XMLHTTP.6.0");
181+
} catch (xhrEx1) {}
182+
try {
183+
return new AXO("Msxml2.XMLHTTP.3.0");
184+
} catch (xhrEx2) {}
185+
try {
186+
return new AXO("Msxml2.XMLHTTP");
187+
} catch (xhrEx3) {}
188188

189-
String_ctr.prototype[$to_locale_string] = function () {
189+
throw new Error("XMLHttpRequest not supported by this browser.");
190+
};
191+
} else {
192+
XHR = XMLHttpRequest;
193+
}
194+
195+
String_ctr[$default_locale] = String_ctr[$default_locale] || "";
196+
String_ctr[$locale] = nav && (nav.language || nav.userLanguage) || "";
197+
198+
if (typeof document !== undef_type) {
199+
var
200+
elts = document.getElementsByTagName("link")
201+
, i = elts.length
202+
, localization
203+
;
204+
205+
while (i--) {
190206
var
191-
parts = String_ctr.locale[$to_lowercase]().split("-")
192-
, i = parts.length
193-
, this_val = this.valueOf()
207+
elt = elts[i]
208+
, rel = (elt.getAttribute("rel") || "")[$to_lowercase]().split(/\s+/)
194209
;
195210

196-
// Iterate through locales starting at most-specific until localization is found
197-
do {
198-
var locale = parts.slice(0, i).join("-");
199-
// load locale if not loaded
200-
if (locale in load_queues) {
201-
process_load_queue(locale);
202-
}
203-
if (locale in localizations && this_val in localizations[locale]) {
204-
return localizations[locale][this_val];
211+
if (l10n_js_media_type.test(elt.type)) {
212+
if (array_index_of.call(rel, "localizations") !== -1) {
213+
// multiple localizations
214+
load(elt.getAttribute("href"));
215+
} else if (array_index_of.call(rel, "localization") !== -1) {
216+
// single localization
217+
localization = {};
218+
localization[(elt.getAttribute("hreflang") || "")[$to_lowercase]()] =
219+
elt.getAttribute("href");
220+
load(localization);
205221
}
206222
}
207-
while (i--);
208-
209-
return this_val;
210-
};
223+
}
224+
}
225+
211226
}());

l10n.min.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)