]>
git.wh0rd.org - tt-rss.git/blob - 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
){
7 has
.add("dojo-preload-i18n-Api",
8 // if true, define the preload localizations machinery
12 1 || has
.add("dojo-v1x-i18n-Api",
13 // if true, define the v1.x i18n functions
18 thisModule
= dojo
.i18n
=
21 // This module implements the dojo/i18n! plugin and the v1.6- i18n API
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.
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)(\/|$)([^\/]*)\/?([^\/]*)/,
38 getAvailableLocales = function(
45 // return a vector of module ids containing all available locales with respect to the target locale
46 // For example, assuming:
48 // - the root bundle indicates specific bundles for "fr" and "fr-ca",
49 // - bundlePath is "myPackage/nls"
50 // - bundleName is "myBundle"
52 // Then a locale argument of "fr-ca" would return
54 // ["myPackage/nls/myBundle", "myPackage/nls/fr/myBundle", "myPackage/nls/fr-ca/myBundle"]
56 // Notice that bundles are returned least-specific to most-specific, starting with the root.
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
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
);
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
);
81 getL10nName
= dojo
.getL10nName = function(moduleName
, bundleName
, locale
){
82 return moduleName
= module
.id
+ "!" + getBundleName(moduleName
, bundleName
, locale
);
85 doLoad = function(require
, bundlePathAndName
, bundlePath
, bundleName
, locale
, load
){
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
]);
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
;
103 normalize = function(id
, toAbsMid
){
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
;
111 getLocalesToLoad = function(targetLocale
){
112 var list
= config
.extraLocale
|| [];
113 list
= lang
.isArray(list
) ? list
: [list
];
114 list
.push(targetLocale
);
118 load = function(id
, require
, load
){
120 // id is in one of the following formats
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.
126 // 2. <path>/nls/<locale>/<bundle>
127 // => load then return the bundle localized to <locale>
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
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.
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
141 // <path>/nls/<bundle>/<locale>
143 // will hold the value. Similarly, then plugin will publish this value to the loader by
145 // define("<path>/nls/<bundle>/<locale>", <bundle-value>);
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.
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:
157 // 1. The client demands "dojo/i18n!some/path/nls/someBundle
159 // 2. The loader demands load(some/path/nls/someBundle)
161 // 3. This plugin require's "some/path/nls/someBundle", which is the root bundle.
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"
167 // 5. Upon receiving all required bundles, the plugin constructs the value of the bundle
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"));
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.
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.
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:
184 // *preload*some/path/nls/someModule*["root", "ab", "ab-cd-ef"]
186 // This indicates the following rollup modules are available:
188 // some/path/nls/someModule_ROOT
189 // some/path/nls/someModule_ab
190 // some/path/nls/someModule_ab-cd-ef
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:
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>,
201 // E.g., given this design, preloading for locale=="ab" can execute the following algorithm:
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]);
211 // Similarly, if "ab-cd" is requested, the algorithm can determine that "ab" is the best available and
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
218 // "*now":function(r){r(['dojo/i18n!*preload*<path>/nls/<module>*<JSON array of available locales>']);}
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.
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:
229 // 1. Layer loads root bundle.
230 // 2. bundle is demanded; plugin loads single localized bundle.
234 // 1. Layer causes preloading of target bundle.
235 // 2. bundle is demanded; service is delayed until preloading complete; bundle is returned.
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.
243 if(has("dojo-preload-i18n-Api")){
244 var split
= id
.split("*"),
245 preloadDemand
= split
[1] == "preload";
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
251 preloadL10n(split
[2], json
.parse(split
[3]), 1, require
);
253 // don't stall the loader!
256 if(preloadDemand
|| waitForPreloads(id
, require
, load
)){
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
,
272 load(lang
.delegate(cache
[loadTarget
]));
275 array
.forEach(loadList
, function(locale
){
276 var target
= bundlePathAndName
+ "/" + locale
;
277 if(has("dojo-preload-i18n-Api")){
278 checkForLegacyModules(target
);
281 doLoad(require
, bundlePathAndName
, bundlePath
, bundleName
, locale
, finish
);
288 if(has("dojo-unit-tests")){
289 var unitTests
= thisModule
.unitTests
= [];
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
;
298 isXd = function(mid
, contextRequire
){
300 contextRequire
.isXdUrl(require
.toUrl(mid
+ ".js")) :
306 preloadWaitQueue
= [],
308 preloadL10n
= thisModule
._preloadLocalizations = function(/*String*/bundlePrefix
, /*Array*/localesGenerated
, /*boolean?*/ guaranteedAmdFormat
, /*function?*/ contextRequire
){
310 // Load available flattened resource bundles associated with a particular module for dojo/locale and all dojo/config.extraLocale (if any)
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.
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.
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
;
324 function doRequire(mid
, callback
){
325 if(isXd(mid
, contextRequire
) || guaranteedAmdFormat
){
326 contextRequire([mid
], callback
);
328 syncRequire([mid
], callback
, contextRequire
);
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("-");
336 if(func(parts
.join("-"))){
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
;
350 doRequire(mid
, function(rollup
){
351 for(var p
in rollup
){
352 cache
[require
.toAbsMid(p
) + "/" + loc
] = rollup
[p
];
355 while(!preloading
&& preloadWaitQueue
.length
){
356 load
.apply(null, preloadWaitQueue
.shift());
366 array
.forEach(dojo
.config
.extraLocale
, preload
);
369 waitForPreloads = function(id
, require
, load
){
371 preloadWaitQueue
.push([id
, require
, load
]);
376 checkForLegacyModules = function()
381 // this code path assumes the dojo loader and won't work with a standard AMD loader
384 // use the function ctor to keep the minifiers away (also come close to global scope, but this is secondary)
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
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
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;};"
401 + "define.called = 0;"
403 + "if(define.called==1)"
404 // bundle called define; therefore signal it's an AMD bundle
405 + "return __amdValue;"
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;"
412 // evaulating the bundle was *neither* an AMD *nor* a legacy flattened bundle
413 // either way, re-eval *after* surrounding with parentheses
416 + "return eval('('+__bundle+')');"
422 syncRequire = function(deps
, callback
, require
){
424 array
.forEach(deps
, function(mid
){
425 var url
= require
.toUrl(mid
+ ".js");
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
);
437 if(result
instanceof Error
){
438 console
.error("failed to evaluate i18n bundle; url=" + url
, result
);
441 // nls/<locale>/<bundle-name> indicates not the root.
442 results
.push(cache
[url
] = (/nls\/[^\/]+\/[^\/]+$/.test(url
) ? result
: {root
:result
, _v1x
:1}));
447 results
.push(cache
[url
]);
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.
458 results
.push(bundle
);
462 require
.getText(url
, true, load
);
464 results
.push(cache
[url
] = {});
472 results
.push(cache
[url
] = {});
479 callback
&& callback
.apply(null, results
);
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
++]]){}
486 result
= object
[names
[i
]];
488 // fallback for incorrect bundle build of 1.6
489 result
= object
[names
[i
].replace(/-/g
,"_")];
492 cache
[target
] = result
;
498 thisModule
.getLocalization = function(moduleName
, bundleName
, locale
){
500 l10nName
= getBundleName(moduleName
, bundleName
, locale
);
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
),
509 function(result_
){ result
= result_
; }
514 if(has("dojo-unit-tests")){
515 unitTests
.push(function(doh
){
516 doh
.register("tests.i18n.unit", function(t
){
519 check
= evalBundle("{prop:1}", checkForLegacyModules
, "nonsense", amdValue
);
520 t
.is({prop
:1}, check
); t
.is(undefined, check
[1]);
522 check
= evalBundle("({prop:1})", checkForLegacyModules
, "nonsense", amdValue
);
523 t
.is({prop
:1}, check
); t
.is(undefined, check
[1]);
525 check
= evalBundle("{'prop-x':1}", checkForLegacyModules
, "nonsense", amdValue
);
526 t
.is({'prop-x':1}, check
); t
.is(undefined, check
[1]);
528 check
= evalBundle("({'prop-x':1})", checkForLegacyModules
, "nonsense", amdValue
);
529 t
.is({'prop-x':1}, check
); t
.is(undefined, check
[1]);
531 check
= evalBundle("define({'prop-x':1})", checkForLegacyModules
, "nonsense", amdValue
);
532 t
.is(amdValue
, check
); t
.is({'prop-x':1}, amdValue
.result
);
534 check
= evalBundle("define('some/module', {'prop-x':1})", checkForLegacyModules
, "nonsense", amdValue
);
535 t
.is(amdValue
, check
); t
.is({'prop-x':1}, amdValue
.result
);
537 check
= evalBundle("this is total nonsense and should throw an error", checkForLegacyModules
, "nonsense", amdValue
);
538 t
.is(check
instanceof Error
, true);
544 return lang
.mixin(thisModule
, {