i18n.js 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. /*
  2. Copyright (c) 2004-2012, The Dojo Foundation All Rights Reserved.
  3. Available via Academic Free License >= 2.1 OR the modified BSD license.
  4. see: http://dojotoolkit.org/license for details
  5. */
  6. if(!dojo._hasResource["dojo.i18n"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  7. dojo._hasResource["dojo.i18n"] = true;
  8. dojo.provide("dojo.i18n");
  9. dojo.getObject("i18n", true, dojo);
  10. /*=====
  11. dojo.i18n = {
  12. // summary: Utility classes to enable loading of resources for internationalization (i18n)
  13. };
  14. =====*/
  15. // when using a real AMD loader, dojo.i18n.getLocalization is already defined by dojo/lib/backCompat
  16. dojo.i18n.getLocalization = dojo.i18n.getLocalization || function(/*String*/packageName, /*String*/bundleName, /*String?*/locale){
  17. // summary:
  18. // Returns an Object containing the localization for a given resource
  19. // bundle in a package, matching the specified locale.
  20. // description:
  21. // Returns a hash containing name/value pairs in its prototypesuch
  22. // that values can be easily overridden. Throws an exception if the
  23. // bundle is not found. Bundle must have already been loaded by
  24. // `dojo.requireLocalization()` or by a build optimization step. NOTE:
  25. // try not to call this method as part of an object property
  26. // definition (`var foo = { bar: dojo.i18n.getLocalization() }`). In
  27. // some loading situations, the bundle may not be available in time
  28. // for the object definition. Instead, call this method inside a
  29. // function that is run after all modules load or the page loads (like
  30. // in `dojo.addOnLoad()`), or in a widget lifecycle method.
  31. // packageName:
  32. // package which is associated with this resource
  33. // bundleName:
  34. // the base filename of the resource bundle (without the ".js" suffix)
  35. // locale:
  36. // the variant to load (optional). By default, the locale defined by
  37. // the host environment: dojo.locale
  38. locale = dojo.i18n.normalizeLocale(locale);
  39. // look for nearest locale match
  40. var elements = locale.split('-');
  41. var module = [packageName,"nls",bundleName].join('.');
  42. var bundle = dojo._loadedModules[module];
  43. if(bundle){
  44. var localization;
  45. for(var i = elements.length; i > 0; i--){
  46. var loc = elements.slice(0, i).join('_');
  47. if(bundle[loc]){
  48. localization = bundle[loc];
  49. break;
  50. }
  51. }
  52. if(!localization){
  53. localization = bundle.ROOT;
  54. }
  55. // make a singleton prototype so that the caller won't accidentally change the values globally
  56. if(localization){
  57. var clazz = function(){};
  58. clazz.prototype = localization;
  59. return new clazz(); // Object
  60. }
  61. }
  62. throw new Error("Bundle not found: " + bundleName + " in " + packageName+" , locale=" + locale);
  63. };
  64. dojo.i18n.normalizeLocale = function(/*String?*/locale){
  65. // summary:
  66. // Returns canonical form of locale, as used by Dojo.
  67. //
  68. // description:
  69. // All variants are case-insensitive and are separated by '-' as specified in [RFC 3066](http://www.ietf.org/rfc/rfc3066.txt).
  70. // If no locale is specified, the dojo.locale is returned. dojo.locale is defined by
  71. // the user agent's locale unless overridden by djConfig.
  72. var result = locale ? locale.toLowerCase() : dojo.locale;
  73. if(result == "root"){
  74. result = "ROOT";
  75. }
  76. return result; // String
  77. };
  78. dojo.i18n._requireLocalization = function(/*String*/moduleName, /*String*/bundleName, /*String?*/locale, /*String?*/availableFlatLocales){
  79. // summary:
  80. // See dojo.requireLocalization()
  81. // description:
  82. // Called by the bootstrap, but factored out so that it is only
  83. // included in the build when needed.
  84. var targetLocale = dojo.i18n.normalizeLocale(locale);
  85. var bundlePackage = [moduleName, "nls", bundleName].join(".");
  86. // NOTE:
  87. // When loading these resources, the packaging does not match what is
  88. // on disk. This is an implementation detail, as this is just a
  89. // private data structure to hold the loaded resources. e.g.
  90. // `tests/hello/nls/en-us/salutations.js` is loaded as the object
  91. // `tests.hello.nls.salutations.en_us={...}` The structure on disk is
  92. // intended to be most convenient for developers and translators, but
  93. // in memory it is more logical and efficient to store in a different
  94. // order. Locales cannot use dashes, since the resulting path will
  95. // not evaluate as valid JS, so we translate them to underscores.
  96. //Find the best-match locale to load if we have available flat locales.
  97. var bestLocale = "";
  98. if(availableFlatLocales){
  99. var flatLocales = availableFlatLocales.split(",");
  100. for(var i = 0; i < flatLocales.length; i++){
  101. //Locale must match from start of string.
  102. //Using ["indexOf"] so customBase builds do not see
  103. //this as a dojo._base.array dependency.
  104. if(targetLocale["indexOf"](flatLocales[i]) == 0){
  105. if(flatLocales[i].length > bestLocale.length){
  106. bestLocale = flatLocales[i];
  107. }
  108. }
  109. }
  110. if(!bestLocale){
  111. bestLocale = "ROOT";
  112. }
  113. }
  114. //See if the desired locale is already loaded.
  115. var tempLocale = availableFlatLocales ? bestLocale : targetLocale;
  116. var bundle = dojo._loadedModules[bundlePackage];
  117. var localizedBundle = null;
  118. if(bundle){
  119. if(dojo.config.localizationComplete && bundle._built){return;}
  120. var jsLoc = tempLocale.replace(/-/g, '_');
  121. var translationPackage = bundlePackage+"."+jsLoc;
  122. localizedBundle = dojo._loadedModules[translationPackage];
  123. }
  124. if(!localizedBundle){
  125. bundle = dojo["provide"](bundlePackage);
  126. var syms = dojo._getModuleSymbols(moduleName);
  127. var modpath = syms.concat("nls").join("/");
  128. var parent;
  129. dojo.i18n._searchLocalePath(tempLocale, availableFlatLocales, function(loc){
  130. var jsLoc = loc.replace(/-/g, '_');
  131. var translationPackage = bundlePackage + "." + jsLoc;
  132. var loaded = false;
  133. if(!dojo._loadedModules[translationPackage]){
  134. // Mark loaded whether it's found or not, so that further load attempts will not be made
  135. dojo["provide"](translationPackage);
  136. var module = [modpath];
  137. if(loc != "ROOT"){module.push(loc);}
  138. module.push(bundleName);
  139. var filespec = module.join("/") + '.js';
  140. loaded = dojo._loadPath(filespec, null, function(hash){
  141. hash = hash.root || hash;
  142. // Use singleton with prototype to point to parent bundle, then mix-in result from loadPath
  143. var clazz = function(){};
  144. clazz.prototype = parent;
  145. bundle[jsLoc] = new clazz();
  146. for(var j in hash){ bundle[jsLoc][j] = hash[j]; }
  147. });
  148. }else{
  149. loaded = true;
  150. }
  151. if(loaded && bundle[jsLoc]){
  152. parent = bundle[jsLoc];
  153. }else{
  154. bundle[jsLoc] = parent;
  155. }
  156. if(availableFlatLocales){
  157. //Stop the locale path searching if we know the availableFlatLocales, since
  158. //the first call to this function will load the only bundle that is needed.
  159. return true;
  160. }
  161. });
  162. }
  163. //Save the best locale bundle as the target locale bundle when we know the
  164. //the available bundles.
  165. if(availableFlatLocales && targetLocale != bestLocale){
  166. bundle[targetLocale.replace(/-/g, '_')] = bundle[bestLocale.replace(/-/g, '_')];
  167. }
  168. };
  169. (function(){
  170. // If other locales are used, dojo.requireLocalization should load them as
  171. // well, by default.
  172. //
  173. // Override dojo.requireLocalization to do load the default bundle, then
  174. // iterate through the extraLocale list and load those translations as
  175. // well, unless a particular locale was requested.
  176. var extra = dojo.config.extraLocale;
  177. if(extra){
  178. if(!extra instanceof Array){
  179. extra = [extra];
  180. }
  181. var req = dojo.i18n._requireLocalization;
  182. dojo.i18n._requireLocalization = function(m, b, locale, availableFlatLocales){
  183. req(m,b,locale, availableFlatLocales);
  184. if(locale){return;}
  185. for(var i=0; i<extra.length; i++){
  186. req(m,b,extra[i], availableFlatLocales);
  187. }
  188. };
  189. }
  190. })();
  191. dojo.i18n._searchLocalePath = function(/*String*/locale, /*Boolean*/down, /*Function*/searchFunc){
  192. // summary:
  193. // A helper method to assist in searching for locale-based resources.
  194. // Will iterate through the variants of a particular locale, either up
  195. // or down, executing a callback function. For example, "en-us" and
  196. // true will try "en-us" followed by "en" and finally "ROOT".
  197. locale = dojo.i18n.normalizeLocale(locale);
  198. var elements = locale.split('-');
  199. var searchlist = [];
  200. for(var i = elements.length; i > 0; i--){
  201. searchlist.push(elements.slice(0, i).join('-'));
  202. }
  203. searchlist.push(false);
  204. if(down){searchlist.reverse();}
  205. for(var j = searchlist.length - 1; j >= 0; j--){
  206. var loc = searchlist[j] || "ROOT";
  207. var stop = searchFunc(loc);
  208. if(stop){ break; }
  209. }
  210. };
  211. dojo.i18n._preloadLocalizations = function(/*String*/bundlePrefix, /*Array*/localesGenerated){
  212. // summary:
  213. // Load built, flattened resource bundles, if available for all
  214. // locales used in the page. Only called by built layer files.
  215. function preload(locale){
  216. locale = dojo.i18n.normalizeLocale(locale);
  217. dojo.i18n._searchLocalePath(locale, true, function(loc){
  218. for(var i=0; i<localesGenerated.length;i++){
  219. if(localesGenerated[i] == loc){
  220. dojo["require"](bundlePrefix+"_"+loc);
  221. return true; // Boolean
  222. }
  223. }
  224. return false; // Boolean
  225. });
  226. }
  227. preload();
  228. var extra = dojo.config.extraLocale||[];
  229. for(var i=0; i<extra.length; i++){
  230. preload(extra[i]);
  231. }
  232. };
  233. }