globalize.js 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. /**
  2. * Globalize v1.0.1
  3. *
  4. * http://github.com/jquery/globalize
  5. *
  6. * Copyright jQuery Foundation and other contributors
  7. * Released under the MIT license
  8. * http://jquery.org/license
  9. *
  10. * Date: 2016-01-20T16:57Z
  11. */
  12. /*!
  13. * Globalize v1.0.1 2016-01-20T16:57Z Released under the MIT license
  14. * http://git.io/TrdQbw
  15. */
  16. (function( root, factory ) {
  17. // UMD returnExports
  18. if ( typeof define === "function" && define.amd ) {
  19. // AMD
  20. define([
  21. "cldr",
  22. "cldr/event"
  23. ], factory );
  24. } else if ( typeof exports === "object" ) {
  25. // Node, CommonJS
  26. module.exports = factory( require( "cldrjs" ) );
  27. } else {
  28. // Global
  29. root.Globalize = factory( root.Cldr );
  30. }
  31. }( this, function( Cldr ) {
  32. /**
  33. * A toString method that outputs meaningful values for objects or arrays and
  34. * still performs as fast as a plain string in case variable is string, or as
  35. * fast as `"" + number` in case variable is a number.
  36. * Ref: http://jsperf.com/my-stringify
  37. */
  38. var toString = function( variable ) {
  39. return typeof variable === "string" ? variable : ( typeof variable === "number" ? "" +
  40. variable : JSON.stringify( variable ) );
  41. };
  42. /**
  43. * formatMessage( message, data )
  44. *
  45. * @message [String] A message with optional {vars} to be replaced.
  46. *
  47. * @data [Array or JSON] Object with replacing-variables content.
  48. *
  49. * Return the formatted message. For example:
  50. *
  51. * - formatMessage( "{0} second", [ 1 ] ); // 1 second
  52. *
  53. * - formatMessage( "{0}/{1}", ["m", "s"] ); // m/s
  54. *
  55. * - formatMessage( "{name} <{email}>", {
  56. * name: "Foo",
  57. * email: "bar@baz.qux"
  58. * }); // Foo <bar@baz.qux>
  59. */
  60. var formatMessage = function( message, data ) {
  61. // Replace {attribute}'s
  62. message = message.replace( /{[0-9a-zA-Z-_. ]+}/g, function( name ) {
  63. name = name.replace( /^{([^}]*)}$/, "$1" );
  64. return toString( data[ name ] );
  65. });
  66. return message;
  67. };
  68. var objectExtend = function() {
  69. var destination = arguments[ 0 ],
  70. sources = [].slice.call( arguments, 1 );
  71. sources.forEach(function( source ) {
  72. var prop;
  73. for ( prop in source ) {
  74. destination[ prop ] = source[ prop ];
  75. }
  76. });
  77. return destination;
  78. };
  79. var createError = function( code, message, attributes ) {
  80. var error;
  81. message = code + ( message ? ": " + formatMessage( message, attributes ) : "" );
  82. error = new Error( message );
  83. error.code = code;
  84. objectExtend( error, attributes );
  85. return error;
  86. };
  87. var validate = function( code, message, check, attributes ) {
  88. if ( !check ) {
  89. throw createError( code, message, attributes );
  90. }
  91. };
  92. var alwaysArray = function( stringOrArray ) {
  93. return Array.isArray( stringOrArray ) ? stringOrArray : stringOrArray ? [ stringOrArray ] : [];
  94. };
  95. var validateCldr = function( path, value, options ) {
  96. var skipBoolean;
  97. options = options || {};
  98. skipBoolean = alwaysArray( options.skip ).some(function( pathRe ) {
  99. return pathRe.test( path );
  100. });
  101. validate( "E_MISSING_CLDR", "Missing required CLDR content `{path}`.", value || skipBoolean, {
  102. path: path
  103. });
  104. };
  105. var validateDefaultLocale = function( value ) {
  106. validate( "E_DEFAULT_LOCALE_NOT_DEFINED", "Default locale has not been defined.",
  107. value !== undefined, {} );
  108. };
  109. var validateParameterPresence = function( value, name ) {
  110. validate( "E_MISSING_PARAMETER", "Missing required parameter `{name}`.",
  111. value !== undefined, { name: name });
  112. };
  113. /**
  114. * range( value, name, minimum, maximum )
  115. *
  116. * @value [Number].
  117. *
  118. * @name [String] name of variable.
  119. *
  120. * @minimum [Number]. The lowest valid value, inclusive.
  121. *
  122. * @maximum [Number]. The greatest valid value, inclusive.
  123. */
  124. var validateParameterRange = function( value, name, minimum, maximum ) {
  125. validate(
  126. "E_PAR_OUT_OF_RANGE",
  127. "Parameter `{name}` has value `{value}` out of range [{minimum}, {maximum}].",
  128. value === undefined || value >= minimum && value <= maximum,
  129. {
  130. maximum: maximum,
  131. minimum: minimum,
  132. name: name,
  133. value: value
  134. }
  135. );
  136. };
  137. var validateParameterType = function( value, name, check, expected ) {
  138. validate(
  139. "E_INVALID_PAR_TYPE",
  140. "Invalid `{name}` parameter ({value}). {expected} expected.",
  141. check,
  142. {
  143. expected: expected,
  144. name: name,
  145. value: value
  146. }
  147. );
  148. };
  149. var validateParameterTypeLocale = function( value, name ) {
  150. validateParameterType(
  151. value,
  152. name,
  153. value === undefined || typeof value === "string" || value instanceof Cldr,
  154. "String or Cldr instance"
  155. );
  156. };
  157. /**
  158. * Function inspired by jQuery Core, but reduced to our use case.
  159. */
  160. var isPlainObject = function( obj ) {
  161. return obj !== null && "" + obj === "[object Object]";
  162. };
  163. var validateParameterTypePlainObject = function( value, name ) {
  164. validateParameterType(
  165. value,
  166. name,
  167. value === undefined || isPlainObject( value ),
  168. "Plain Object"
  169. );
  170. };
  171. var alwaysCldr = function( localeOrCldr ) {
  172. return localeOrCldr instanceof Cldr ? localeOrCldr : new Cldr( localeOrCldr );
  173. };
  174. // ref: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions?redirectlocale=en-US&redirectslug=JavaScript%2FGuide%2FRegular_Expressions
  175. var regexpEscape = function( string ) {
  176. return string.replace( /([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1" );
  177. };
  178. var stringPad = function( str, count, right ) {
  179. var length;
  180. if ( typeof str !== "string" ) {
  181. str = String( str );
  182. }
  183. for ( length = str.length; length < count; length += 1 ) {
  184. str = ( right ? ( str + "0" ) : ( "0" + str ) );
  185. }
  186. return str;
  187. };
  188. function validateLikelySubtags( cldr ) {
  189. cldr.once( "get", validateCldr );
  190. cldr.get( "supplemental/likelySubtags" );
  191. }
  192. /**
  193. * [new] Globalize( locale|cldr )
  194. *
  195. * @locale [String]
  196. *
  197. * @cldr [Cldr instance]
  198. *
  199. * Create a Globalize instance.
  200. */
  201. function Globalize( locale ) {
  202. if ( !( this instanceof Globalize ) ) {
  203. return new Globalize( locale );
  204. }
  205. validateParameterPresence( locale, "locale" );
  206. validateParameterTypeLocale( locale, "locale" );
  207. this.cldr = alwaysCldr( locale );
  208. validateLikelySubtags( this.cldr );
  209. }
  210. /**
  211. * Globalize.load( json, ... )
  212. *
  213. * @json [JSON]
  214. *
  215. * Load resolved or unresolved cldr data.
  216. * Somewhat equivalent to previous Globalize.addCultureInfo(...).
  217. */
  218. Globalize.load = function() {
  219. // validations are delegated to Cldr.load().
  220. Cldr.load.apply( Cldr, arguments );
  221. };
  222. /**
  223. * Globalize.locale( [locale|cldr] )
  224. *
  225. * @locale [String]
  226. *
  227. * @cldr [Cldr instance]
  228. *
  229. * Set default Cldr instance if locale or cldr argument is passed.
  230. *
  231. * Return the default Cldr instance.
  232. */
  233. Globalize.locale = function( locale ) {
  234. validateParameterTypeLocale( locale, "locale" );
  235. if ( arguments.length ) {
  236. this.cldr = alwaysCldr( locale );
  237. validateLikelySubtags( this.cldr );
  238. }
  239. return this.cldr;
  240. };
  241. /**
  242. * Optimization to avoid duplicating some internal functions across modules.
  243. */
  244. Globalize._alwaysArray = alwaysArray;
  245. Globalize._createError = createError;
  246. Globalize._formatMessage = formatMessage;
  247. Globalize._isPlainObject = isPlainObject;
  248. Globalize._objectExtend = objectExtend;
  249. Globalize._regexpEscape = regexpEscape;
  250. Globalize._stringPad = stringPad;
  251. Globalize._validate = validate;
  252. Globalize._validateCldr = validateCldr;
  253. Globalize._validateDefaultLocale = validateDefaultLocale;
  254. Globalize._validateParameterPresence = validateParameterPresence;
  255. Globalize._validateParameterRange = validateParameterRange;
  256. Globalize._validateParameterTypePlainObject = validateParameterTypePlainObject;
  257. Globalize._validateParameterType = validateParameterType;
  258. return Globalize;
  259. }));