]> git.wh0rd.org - tt-rss.git/blob - lib/dojo/i18n.js.uncompressed.js
upgrade dojo to 1.8.3 (refs #570)
[tt-rss.git] / lib / dojo / i18n.js.uncompressed.js
1 define("dojo/i18n", ["./_base/kernel", "require", "./has", "./_base/array", "./_base/config", "./_base/lang", "./_base/xhr", "./json", "module"],
2 function(dojo, require, has, array, config, lang, xhr, json, module){
3
4 // module:
5 // dojo/i18n
6
7 has.add("dojo-preload-i18n-Api",
8 // if true, define the preload localizations machinery
9 1
10 );
11
12 1 || has.add("dojo-v1x-i18n-Api",
13 // if true, define the v1.x i18n functions
14 1
15 );
16
17 var
18 thisModule = dojo.i18n =
19 {
20 // summary:
21 // This module implements the dojo/i18n! plugin and the v1.6- i18n API
22 // description:
23 // We choose to include our own plugin to leverage functionality already contained in dojo
24 // and thereby reduce the size of the plugin compared to various loader implementations. Also, this
25 // allows foreign AMD loaders to be used without their plugins.
26 },
27
28 nlsRe =
29 // regexp for reconstructing the master bundle name from parts of the regexp match
30 // nlsRe.exec("foo/bar/baz/nls/en-ca/foo") gives:
31 // ["foo/bar/baz/nls/en-ca/foo", "foo/bar/baz/nls/", "/", "/", "en-ca", "foo"]
32 // nlsRe.exec("foo/bar/baz/nls/foo") gives:
33 // ["foo/bar/baz/nls/foo", "foo/bar/baz/nls/", "/", "/", "foo", ""]
34 // so, if match[5] is blank, it means this is the top bundle definition.
35 // courtesy of http://requirejs.org
36 /(^.*(^|\/)nls)(\/|$)([^\/]*)\/?([^\/]*)/,
37
38 getAvailableLocales = function(
39 root,
40 locale,
41 bundlePath,
42 bundleName
43 ){
44 // summary:
45 // return a vector of module ids containing all available locales with respect to the target locale
46 // For example, assuming:
47 //
48 // - the root bundle indicates specific bundles for "fr" and "fr-ca",
49 // - bundlePath is "myPackage/nls"
50 // - bundleName is "myBundle"
51 //
52 // Then a locale argument of "fr-ca" would return
53 //
54 // ["myPackage/nls/myBundle", "myPackage/nls/fr/myBundle", "myPackage/nls/fr-ca/myBundle"]
55 //
56 // Notice that bundles are returned least-specific to most-specific, starting with the root.
57 //
58 // If root===false indicates we're working with a pre-AMD i18n bundle that doesn't tell about the available locales;
59 // therefore, assume everything is available and get 404 errors that indicate a particular localization is not available
60
61 for(var result = [bundlePath + bundleName], localeParts = locale.split("-"), current = "", i = 0; i<localeParts.length; i++){
62 current += (current ? "-" : "") + localeParts[i];
63 if(!root || root[current]){
64 result.push(bundlePath + current + "/" + bundleName);
65 }
66 }
67 return result;
68 },
69
70 cache = {},
71
72 getBundleName = function(moduleName, bundleName, locale){
73 locale = locale ? locale.toLowerCase() : dojo.locale;
74 moduleName = moduleName.replace(/\./g, "/");
75 bundleName = bundleName.replace(/\./g, "/");
76 return (/root/i.test(locale)) ?
77 (moduleName + "/nls/" + bundleName) :
78 (moduleName + "/nls/" + locale + "/" + bundleName);
79 },
80
81 getL10nName = dojo.getL10nName = function(moduleName, bundleName, locale){
82 return moduleName = module.id + "!" + getBundleName(moduleName, bundleName, locale);
83 },
84
85 doLoad = function(require, bundlePathAndName, bundlePath, bundleName, locale, load){
86 // summary:
87 // get the root bundle which instructs which other bundles are required to construct the localized bundle
88 require([bundlePathAndName], function(root){
89 var current = lang.clone(root.root),
90 availableLocales = getAvailableLocales(!root._v1x && root, locale, bundlePath, bundleName);
91 require(availableLocales, function(){
92 for (var i = 1; i<availableLocales.length; i++){
93 current = lang.mixin(lang.clone(current), arguments[i]);
94 }
95 // target may not have been resolve (e.g., maybe only "fr" exists when "fr-ca" was requested)
96 var target = bundlePathAndName + "/" + locale;
97 cache[target] = current;
98 load();
99 });
100 });
101 },
102
103 normalize = function(id, toAbsMid){
104 // summary:
105 // id may be relative.
106 // preload has form `*preload*<path>/nls/<module>*<flattened locales>` and
107 // therefore never looks like a relative
108 return /^\./.test(id) ? toAbsMid(id) : id;
109 },
110
111 getLocalesToLoad = function(targetLocale){
112 var list = config.extraLocale || [];
113 list = lang.isArray(list) ? list : [list];
114 list.push(targetLocale);
115 return list;
116 },
117
118 load = function(id, require, load){
119 // summary:
120 // id is in one of the following formats
121 //
122 // 1. <path>/nls/<bundle>
123 // => load the bundle, localized to config.locale; load all bundles localized to
124 // config.extraLocale (if any); return the loaded bundle localized to config.locale.
125 //
126 // 2. <path>/nls/<locale>/<bundle>
127 // => load then return the bundle localized to <locale>
128 //
129 // 3. *preload*<path>/nls/<module>*<JSON array of available locales>
130 // => for config.locale and all config.extraLocale, load all bundles found
131 // in the best-matching bundle rollup. A value of 1 is returned, which
132 // is meaningless other than to say the plugin is executing the requested
133 // preloads
134 //
135 // In cases 1 and 2, <path> is always normalized to an absolute module id upon entry; see
136 // normalize. In case 3, it <path> is assumed to be absolute; this is arranged by the builder.
137 //
138 // To load a bundle means to insert the bundle into the plugin's cache and publish the bundle
139 // value to the loader. Given <path>, <bundle>, and a particular <locale>, the cache key
140 //
141 // <path>/nls/<bundle>/<locale>
142 //
143 // will hold the value. Similarly, then plugin will publish this value to the loader by
144 //
145 // define("<path>/nls/<bundle>/<locale>", <bundle-value>);
146 //
147 // Given this algorithm, other machinery can provide fast load paths be preplacing
148 // values in the plugin's cache, which is public. When a load is demanded the
149 // cache is inspected before starting any loading. Explicitly placing values in the plugin
150 // cache is an advanced/experimental feature that should not be needed; use at your own risk.
151 //
152 // For the normal AMD algorithm, the root bundle is loaded first, which instructs the
153 // plugin what additional localized bundles are required for a particular locale. These
154 // additional locales are loaded and a mix of the root and each progressively-specific
155 // locale is returned. For example:
156 //
157 // 1. The client demands "dojo/i18n!some/path/nls/someBundle
158 //
159 // 2. The loader demands load(some/path/nls/someBundle)
160 //
161 // 3. This plugin require's "some/path/nls/someBundle", which is the root bundle.
162 //
163 // 4. Assuming config.locale is "ab-cd-ef" and the root bundle indicates that localizations
164 // are available for "ab" and "ab-cd-ef" (note the missing "ab-cd", then the plugin
165 // requires "some/path/nls/ab/someBundle" and "some/path/nls/ab-cd-ef/someBundle"
166 //
167 // 5. Upon receiving all required bundles, the plugin constructs the value of the bundle
168 // ab-cd-ef as...
169 //
170 // mixin(mixin(mixin({}, require("some/path/nls/someBundle"),
171 // require("some/path/nls/ab/someBundle")),
172 // require("some/path/nls/ab-cd-ef/someBundle"));
173 //
174 // This value is inserted into the cache and published to the loader at the
175 // key/module-id some/path/nls/someBundle/ab-cd-ef.
176 //
177 // The special preload signature (case 3) instructs the plugin to stop servicing all normal requests
178 // (further preload requests will be serviced) until all ongoing preloading has completed.
179 //
180 // The preload signature instructs the plugin that a special rollup module is available that contains
181 // one or more flattened, localized bundles. The JSON array of available locales indicates which locales
182 // are available. Here is an example:
183 //
184 // *preload*some/path/nls/someModule*["root", "ab", "ab-cd-ef"]
185 //
186 // This indicates the following rollup modules are available:
187 //
188 // some/path/nls/someModule_ROOT
189 // some/path/nls/someModule_ab
190 // some/path/nls/someModule_ab-cd-ef
191 //
192 // Each of these modules is a normal AMD module that contains one or more flattened bundles in a hash.
193 // For example, assume someModule contained the bundles some/bundle/path/someBundle and
194 // some/bundle/path/someOtherBundle, then some/path/nls/someModule_ab would be expressed as follows:
195 //
196 // define({
197 // some/bundle/path/someBundle:<value of someBundle, flattened with respect to locale ab>,
198 // some/bundle/path/someOtherBundle:<value of someOtherBundle, flattened with respect to locale ab>,
199 // });
200 //
201 // E.g., given this design, preloading for locale=="ab" can execute the following algorithm:
202 //
203 // require(["some/path/nls/someModule_ab"], function(rollup){
204 // for(var p in rollup){
205 // var id = p + "/ab",
206 // cache[id] = rollup[p];
207 // define(id, rollup[p]);
208 // }
209 // });
210 //
211 // Similarly, if "ab-cd" is requested, the algorithm can determine that "ab" is the best available and
212 // load accordingly.
213 //
214 // The builder will write such rollups for every layer if a non-empty localeList profile property is
215 // provided. Further, the builder will include the following cache entry in the cache associated with
216 // any layer.
217 //
218 // "*now":function(r){r(['dojo/i18n!*preload*<path>/nls/<module>*<JSON array of available locales>']);}
219 //
220 // The *now special cache module instructs the loader to apply the provided function to context-require
221 // with respect to the particular layer being defined. This causes the plugin to hold all normal service
222 // requests until all preloading is complete.
223 //
224 // Notice that this algorithm is rarely better than the standard AMD load algorithm. Consider the normal case
225 // where the target locale has a single segment and a layer depends on a single bundle:
226 //
227 // Without Preloads:
228 //
229 // 1. Layer loads root bundle.
230 // 2. bundle is demanded; plugin loads single localized bundle.
231 //
232 // With Preloads:
233 //
234 // 1. Layer causes preloading of target bundle.
235 // 2. bundle is demanded; service is delayed until preloading complete; bundle is returned.
236 //
237 // In each case a single transaction is required to load the target bundle. In cases where multiple bundles
238 // are required and/or the locale has multiple segments, preloads still requires a single transaction whereas
239 // the normal path requires an additional transaction for each additional bundle/locale-segment. However all
240 // of these additional transactions can be done concurrently. Owing to this analysis, the entire preloading
241 // algorithm can be discard during a build by setting the has feature dojo-preload-i18n-Api to false.
242
243 if(has("dojo-preload-i18n-Api")){
244 var split = id.split("*"),
245 preloadDemand = split[1] == "preload";
246 if(preloadDemand){
247 if(!cache[id]){
248 // use cache[id] to prevent multiple preloads of the same preload; this shouldn't happen, but
249 // who knows what over-aggressive human optimizers may attempt
250 cache[id] = 1;
251 preloadL10n(split[2], json.parse(split[3]), 1, require);
252 }
253 // don't stall the loader!
254 load(1);
255 }
256 if(preloadDemand || waitForPreloads(id, require, load)){
257 return;
258 }
259 }
260
261 var match = nlsRe.exec(id),
262 bundlePath = match[1] + "/",
263 bundleName = match[5] || match[4],
264 bundlePathAndName = bundlePath + bundleName,
265 localeSpecified = (match[5] && match[4]),
266 targetLocale = localeSpecified || dojo.locale,
267 loadTarget = bundlePathAndName + "/" + targetLocale,
268 loadList = localeSpecified ? [targetLocale] : getLocalesToLoad(targetLocale),
269 remaining = loadList.length,
270 finish = function(){
271 if(!--remaining){
272 load(lang.delegate(cache[loadTarget]));
273 }
274 };
275 array.forEach(loadList, function(locale){
276 var target = bundlePathAndName + "/" + locale;
277 if(has("dojo-preload-i18n-Api")){
278 checkForLegacyModules(target);
279 }
280 if(!cache[target]){
281 doLoad(require, bundlePathAndName, bundlePath, bundleName, locale, finish);
282 }else{
283 finish();
284 }
285 });
286 };
287
288 if(has("dojo-unit-tests")){
289 var unitTests = thisModule.unitTests = [];
290 }
291
292 if(has("dojo-preload-i18n-Api") || 1 ){
293 var normalizeLocale = thisModule.normalizeLocale = function(locale){
294 var result = locale ? locale.toLowerCase() : dojo.locale;
295 return result == "root" ? "ROOT" : result;
296 },
297
298 isXd = function(mid, contextRequire){
299 return ( 1 && 1 ) ?
300 contextRequire.isXdUrl(require.toUrl(mid + ".js")) :
301 true;
302 },
303
304 preloading = 0,
305
306 preloadWaitQueue = [],
307
308 preloadL10n = thisModule._preloadLocalizations = function(/*String*/bundlePrefix, /*Array*/localesGenerated, /*boolean?*/ guaranteedAmdFormat, /*function?*/ contextRequire){
309 // summary:
310 // Load available flattened resource bundles associated with a particular module for dojo/locale and all dojo/config.extraLocale (if any)
311 // description:
312 // Only called by built layer files. The entire locale hierarchy is loaded. For example,
313 // if locale=="ab-cd", then ROOT, "ab", and "ab-cd" are loaded. This is different than v1.6-
314 // in that the v1.6- would only load ab-cd...which was *always* flattened.
315 //
316 // If guaranteedAmdFormat is true, then the module can be loaded with require thereby circumventing the detection algorithm
317 // and the extra possible extra transaction.
318
319 // If this function is called from legacy code, then guaranteedAmdFormat and contextRequire will be undefined. Since the function
320 // needs a require in order to resolve module ids, fall back to the context-require associated with this dojo/i18n module, which
321 // itself may have been mapped.
322 contextRequire = contextRequire || require;
323
324 function doRequire(mid, callback){
325 if(isXd(mid, contextRequire) || guaranteedAmdFormat){
326 contextRequire([mid], callback);
327 }else{
328 syncRequire([mid], callback, contextRequire);
329 }
330 }
331
332 function forEachLocale(locale, func){
333 // given locale= "ab-cd-ef", calls func on "ab-cd-ef", "ab-cd", "ab", "ROOT"; stops calling the first time func returns truthy
334 var parts = locale.split("-");
335 while(parts.length){
336 if(func(parts.join("-"))){
337 return;
338 }
339 parts.pop();
340 }
341 func("ROOT");
342 }
343
344 function preload(locale){
345 locale = normalizeLocale(locale);
346 forEachLocale(locale, function(loc){
347 if(array.indexOf(localesGenerated, loc)>=0){
348 var mid = bundlePrefix.replace(/\./g, "/")+"_"+loc;
349 preloading++;
350 doRequire(mid, function(rollup){
351 for(var p in rollup){
352 cache[require.toAbsMid(p) + "/" + loc] = rollup[p];
353 }
354 --preloading;
355 while(!preloading && preloadWaitQueue.length){
356 load.apply(null, preloadWaitQueue.shift());
357 }
358 });
359 return true;
360 }
361 return false;
362 });
363 }
364
365 preload();
366 array.forEach(dojo.config.extraLocale, preload);
367 },
368
369 waitForPreloads = function(id, require, load){
370 if(preloading){
371 preloadWaitQueue.push([id, require, load]);
372 }
373 return preloading;
374 },
375
376 checkForLegacyModules = function()
377 {};
378 }
379
380 if( 1 ){
381 // this code path assumes the dojo loader and won't work with a standard AMD loader
382 var amdValue = {},
383 evalBundle =
384 // use the function ctor to keep the minifiers away (also come close to global scope, but this is secondary)
385 new Function(
386 "__bundle", // the bundle to evalutate
387 "__checkForLegacyModules", // a function that checks if __bundle defined __mid in the global space
388 "__mid", // the mid that __bundle is intended to define
389 "__amdValue",
390
391 // returns one of:
392 // 1 => the bundle was an AMD bundle
393 // a legacy bundle object that is the value of __mid
394 // instance of Error => could not figure out how to evaluate bundle
395
396 // used to detect when __bundle calls define
397 "var define = function(mid, factory){define.called = 1; __amdValue.result = factory || mid;},"
398 + " require = function(){define.called = 1;};"
399
400 + "try{"
401 + "define.called = 0;"
402 + "eval(__bundle);"
403 + "if(define.called==1)"
404 // bundle called define; therefore signal it's an AMD bundle
405 + "return __amdValue;"
406
407 + "if((__checkForLegacyModules = __checkForLegacyModules(__mid)))"
408 // bundle was probably a v1.6- built NLS flattened NLS bundle that defined __mid in the global space
409 + "return __checkForLegacyModules;"
410
411 + "}catch(e){}"
412 // evaulating the bundle was *neither* an AMD *nor* a legacy flattened bundle
413 // either way, re-eval *after* surrounding with parentheses
414
415 + "try{"
416 + "return eval('('+__bundle+')');"
417 + "}catch(e){"
418 + "return e;"
419 + "}"
420 ),
421
422 syncRequire = function(deps, callback, require){
423 var results = [];
424 array.forEach(deps, function(mid){
425 var url = require.toUrl(mid + ".js");
426
427 function load(text){
428 var result = evalBundle(text, checkForLegacyModules, mid, amdValue);
429 if(result===amdValue){
430 // the bundle was an AMD module; re-inject it through the normal AMD path
431 // we gotta do this since it could be an anonymous module and simply evaluating
432 // the text here won't provide the loader with the context to know what
433 // module is being defined()'d. With browser caching, this should be free; further
434 // this entire code path can be circumvented by using the AMD format to begin with
435 results.push(cache[url] = amdValue.result);
436 }else{
437 if(result instanceof Error){
438 console.error("failed to evaluate i18n bundle; url=" + url, result);
439 result = {};
440 }
441 // nls/<locale>/<bundle-name> indicates not the root.
442 results.push(cache[url] = (/nls\/[^\/]+\/[^\/]+$/.test(url) ? result : {root:result, _v1x:1}));
443 }
444 }
445
446 if(cache[url]){
447 results.push(cache[url]);
448 }else{
449 var bundle = require.syncLoadNls(mid);
450 // don't need to check for legacy since syncLoadNls returns a module if the module
451 // (1) was already loaded, or (2) was in the cache. In case 1, if syncRequire is called
452 // from getLocalization --> load, then load will have called checkForLegacyModules() before
453 // calling syncRequire; if syncRequire is called from preloadLocalizations, then we
454 // don't care about checkForLegacyModules() because that will be done when a particular
455 // bundle is actually demanded. In case 2, checkForLegacyModules() is never relevant
456 // because cached modules are always v1.7+ built modules.
457 if(bundle){
458 results.push(bundle);
459 }else{
460 if(!xhr){
461 try{
462 require.getText(url, true, load);
463 }catch(e){
464 results.push(cache[url] = {});
465 }
466 }else{
467 xhr.get({
468 url:url,
469 sync:true,
470 load:load,
471 error:function(){
472 results.push(cache[url] = {});
473 }
474 });
475 }
476 }
477 }
478 });
479 callback && callback.apply(null, results);
480 };
481
482 checkForLegacyModules = function(target){
483 // legacy code may have already loaded [e.g] the raw bundle x/y/z at x.y.z; when true, push into the cache
484 for(var result, names = target.split("/"), object = dojo.global[names[0]], i = 1; object && i<names.length-1; object = object[names[i++]]){}
485 if(object){
486 result = object[names[i]];
487 if(!result){
488 // fallback for incorrect bundle build of 1.6
489 result = object[names[i].replace(/-/g,"_")];
490 }
491 if(result){
492 cache[target] = result;
493 }
494 }
495 return result;
496 };
497
498 thisModule.getLocalization = function(moduleName, bundleName, locale){
499 var result,
500 l10nName = getBundleName(moduleName, bundleName, locale);
501 load(
502 l10nName,
503
504 // isXd() and syncRequire() need a context-require in order to resolve the mid with respect to a reference module.
505 // Since this legacy function does not have the concept of a reference module, resolve with respect to this
506 // dojo/i18n module, which, itself may have been mapped.
507 (!isXd(l10nName, require) ? function(deps, callback){ syncRequire(deps, callback, require); } : require),
508
509 function(result_){ result = result_; }
510 );
511 return result;
512 };
513
514 if(has("dojo-unit-tests")){
515 unitTests.push(function(doh){
516 doh.register("tests.i18n.unit", function(t){
517 var check;
518
519 check = evalBundle("{prop:1}", checkForLegacyModules, "nonsense", amdValue);
520 t.is({prop:1}, check); t.is(undefined, check[1]);
521
522 check = evalBundle("({prop:1})", checkForLegacyModules, "nonsense", amdValue);
523 t.is({prop:1}, check); t.is(undefined, check[1]);
524
525 check = evalBundle("{'prop-x':1}", checkForLegacyModules, "nonsense", amdValue);
526 t.is({'prop-x':1}, check); t.is(undefined, check[1]);
527
528 check = evalBundle("({'prop-x':1})", checkForLegacyModules, "nonsense", amdValue);
529 t.is({'prop-x':1}, check); t.is(undefined, check[1]);
530
531 check = evalBundle("define({'prop-x':1})", checkForLegacyModules, "nonsense", amdValue);
532 t.is(amdValue, check); t.is({'prop-x':1}, amdValue.result);
533
534 check = evalBundle("define('some/module', {'prop-x':1})", checkForLegacyModules, "nonsense", amdValue);
535 t.is(amdValue, check); t.is({'prop-x':1}, amdValue.result);
536
537 check = evalBundle("this is total nonsense and should throw an error", checkForLegacyModules, "nonsense", amdValue);
538 t.is(check instanceof Error, true);
539 });
540 });
541 }
542 }
543
544 return lang.mixin(thisModule, {
545 dynamic:true,
546 normalize:normalize,
547 load:load,
548 cache:cache
549 });
550 });