i18n.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. /**
  2. * Plugin based on requirejs i18n
  3. * see: http://github.com/requirejs/i18n for details
  4. */
  5. define(["./i18n/common", "./i18n/build", "module"], function (common, build, module) {
  6. var localesList,
  7. writePluginFile,
  8. mixin = common.mixin,
  9. eachProp = common.eachProp,
  10. parseName = common.parseName,
  11. getMasterMid = common.getMasterMid,
  12. normalizeBundlesMap = function (bundlesMap) {
  13. var result = {};
  14. eachProp(bundlesMap, function (layer, bundleList) {
  15. bundleList.forEach(function (bundle) {
  16. result[bundle] = layer;
  17. });
  18. });
  19. return result;
  20. },
  21. // Transform a bundle from a language layer to a root bundle.
  22. rootify = function (bundle, locale) {
  23. var result = {};
  24. if (bundle._pseudoRoot) {
  25. result[locale] = {};
  26. mixin(result, bundle._pseudoRoot);
  27. delete bundle._pseudoRoot;
  28. mixin(result[locale], bundle);
  29. bundle = result;
  30. }
  31. return bundle;
  32. },
  33. // Construct the best language bundle by merging from most specific locale to less specific locale.
  34. resolveAMD = function (name, req, onLoad) {
  35. var masterMid = getMasterMid(name);
  36. //First, fetch the master bundle, it knows what locales are available.
  37. req([masterMid], function (master) {
  38. var getBundleAndMixin = function (prefix, suffix, locale, value) {
  39. var mixBundle = function (bundle) {
  40. mixin(value, bundle);
  41. locale = common.getParentLocale(locale);
  42. if (!bundle._flattened && locale) {
  43. getBundleAndMixin(prefix, suffix, locale, value);
  44. } else {
  45. value._flattened = true;
  46. onLoad(value);
  47. }
  48. };
  49. if (master[locale] === true || master[locale] === 1) {
  50. req([prefix + locale + '/' + suffix], mixBundle);
  51. } else {
  52. // locale is on the master bundle or locale is unexisting
  53. mixBundle(master[locale] || {});
  54. }
  55. };
  56. master = rootify(master, name.masterLocale);
  57. getBundleAndMixin(name.prefix, name.suffix, name.requestedLocale, {});
  58. });
  59. },
  60. getLayer = function (name, layer, moduleConfig, getParentLocale, req, onLoad) {
  61. var locale = name.requestedLocale,
  62. localesList = moduleConfig.localesMap[layer];
  63. while (locale && localesList.indexOf(locale) < 0) {
  64. locale = getParentLocale(locale);
  65. }
  66. if (locale) {
  67. name.masterLocale = locale;
  68. req([layer + "_" + locale], function () {
  69. pickFromLayer(name, moduleConfig, req, onLoad);
  70. });
  71. } else {
  72. console.log("i18n: no relevant layer " + layer + " found for locale " + name.requestedLocale + ".");
  73. onLoad();
  74. }
  75. },
  76. tryLayer = function (name, layer, moduleConfig, getParentLocale, req, onLoad) {
  77. var helper = function (locale) {
  78. if (locale) {
  79. req(["maybe!" + layer + "_" + locale], function (bundle) {
  80. if (bundle) {
  81. name.masterLocale = locale;
  82. pickFromLayer(name, moduleConfig, req, onLoad);
  83. } else {
  84. helper(getParentLocale(locale));
  85. }
  86. });
  87. } else {
  88. console.log("i18n: no relevant layer " + layer + " found for locale " + name.requestedLocale + ".");
  89. onLoad();
  90. }
  91. };
  92. helper(name.requestedLocale);
  93. },
  94. pickFromLayer = function (name, moduleConfig, req, onLoad) {
  95. var masterMid = getMasterMid(name);
  96. if (name.requestedLocale === name.masterLocale || moduleConfig.layerOnly || !moduleConfig.enhanceLayer) {
  97. req([masterMid], function (bundle) {
  98. if (bundle.root) {
  99. bundle = bundle.root;
  100. }
  101. onLoad(bundle);
  102. });
  103. } else {
  104. resolveAMD(name, req, onLoad);
  105. }
  106. };
  107. return {
  108. /* jshint maxcomplexity:15 */
  109. load: function (name, req, onLoad, config) {
  110. if (!name) {
  111. onLoad();
  112. return;
  113. }
  114. config = config || {};
  115. var moduleConfig = {},
  116. masterMid,
  117. layer;
  118. // Copy the config
  119. mixin(moduleConfig, typeof module.config === "function" ? module.config() || {} : {});
  120. if (config.isBuild) {
  121. localesList = moduleConfig.localesList;
  122. onLoad();
  123. return;
  124. }
  125. moduleConfig.enhanceLayer = moduleConfig.enhanceLayer === undefined ? true : moduleConfig.enhanceLayer;
  126. // Parse name and set the locale if a top level bundle is required
  127. name = parseName(name);
  128. name.requestedLocale = name.requestedLocale || common.getLocale(moduleConfig.locale || config.locale);
  129. masterMid = getMasterMid(name);
  130. // If there is no layer, classic AMD mode
  131. if (!moduleConfig.bundlesMap) {
  132. resolveAMD(name, req, onLoad);
  133. return;
  134. }
  135. // From now on there is at least one layer available
  136. // Check if requested module is in a layer
  137. moduleConfig.bundlesMap = normalizeBundlesMap(moduleConfig.bundlesMap);
  138. layer = moduleConfig.bundlesMap[masterMid];
  139. if (!layer && moduleConfig.layerOnly) {
  140. console.log("i18n: module " + masterMid + " not found in layer.");
  141. onLoad();
  142. return;
  143. } else if (!layer) {
  144. resolveAMD(name, req, onLoad);
  145. return;
  146. }
  147. // The module is in a layer
  148. if (moduleConfig.languagePack) {
  149. // Drop language pack mode, hence need to try every possible layer
  150. tryLayer(name, layer, moduleConfig, common.getParentLocale, req, onLoad);
  151. return;
  152. } else {
  153. // There is a locale list for the layer
  154. getLayer(name, layer, moduleConfig, common.getParentLocale, req, onLoad);
  155. return;
  156. }
  157. },
  158. /* jshint maxcomplexity:10 */
  159. write: function (pluginName, moduleName, write) {
  160. var name = parseName(moduleName),
  161. bundle;
  162. if (name.requestedLocale) {
  163. bundle = build.resolveSync(name.requestedLocale, name);
  164. if (name.requestedLocale !== "root") {
  165. bundle._pseudoRoot = {};
  166. bundle._flattened = true;
  167. }
  168. write.asModule(pluginName + "!" + moduleName, "define(" + JSON.stringify(bundle) + ")");
  169. } else {
  170. build.addBundleToNlsLayer(name);
  171. }
  172. },
  173. writeFile: function (pluginName, resource, requirejs, writeFile) {
  174. writePluginFile = writeFile;
  175. },
  176. onLayerEnd: function (write, data) {
  177. if (data.name && data.path) {
  178. var layersContent;
  179. build.setLocalesList(localesList);
  180. layersContent = build.getLayersContent();
  181. build.writeLayers(layersContent, data, writePluginFile);
  182. build.writeConfig(module.id, data, write);
  183. }
  184. build.reset();
  185. }
  186. };
  187. });