currency.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. // Copyright 2009 The Closure Library Authors. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS-IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. /**
  15. * @fileoverview A utility to get better currency format pattern.
  16. *
  17. * This module implements a new currency format representation model. It
  18. * provides 3 currency representation forms: global, portable and local. Local
  19. * format is the most popular format people use to represent currency in its
  20. * circulating country without worrying about how it should be distinguished
  21. * from other currencies. Global format is a formal representation in context
  22. * of multiple currencies in same page, it is ISO 4217 currency code. Portable
  23. * format is a compromise between global and local. It looks similar to how
  24. * people would like to see how their currency is being represented in other
  25. * media. While at the same time, it should be distinguishable to world's
  26. * popular currencies (like USD, EUR) and currencies somewhat relevant in the
  27. * area (like CNY in HK, though native currency is HKD). There is no guarantee
  28. * of uniqueness.
  29. *
  30. */
  31. goog.provide('goog.i18n.currency');
  32. goog.provide('goog.i18n.currency.CurrencyInfo');
  33. goog.provide('goog.i18n.currency.CurrencyInfoTier2');
  34. /**
  35. * The mask of precision field.
  36. * @private
  37. */
  38. goog.i18n.currency.PRECISION_MASK_ = 0x07;
  39. /**
  40. * Whether the currency sign should be positioned after the number.
  41. * @private
  42. */
  43. goog.i18n.currency.POSITION_FLAG_ = 0x10;
  44. /**
  45. * Whether a space should be inserted between the number and currency sign.
  46. * @private
  47. */
  48. goog.i18n.currency.SPACE_FLAG_ = 0x20;
  49. /**
  50. * Whether tier2 was enabled already by calling addTier2Support().
  51. * @private
  52. */
  53. goog.i18n.currency.tier2Enabled_ = false;
  54. /**
  55. * Tests if currency is available.
  56. *
  57. * Note: If the currency is not available it might be in the tier2 currency set:
  58. * {@link goog.i18n.currency.CurrencyInfoTier2}. If that is the case call
  59. * {@link goog.i18n.currency.addTier2Support} before calling any other function
  60. * in this namespace.
  61. *
  62. * @param {string} currencyCode Currency code to tested.
  63. * @return {boolean} If the currency is available.
  64. */
  65. goog.i18n.currency.isAvailable = function(currencyCode) {
  66. return currencyCode in goog.i18n.currency.CurrencyInfo;
  67. };
  68. /**
  69. * This function will add tier2 currency support. Be default, only tier1
  70. * (most popular currencies) are supported. If an application really needs
  71. * to support some of the rarely used currencies, it should call this function
  72. * before any other functions in this namespace.
  73. */
  74. goog.i18n.currency.addTier2Support = function() {
  75. // Protection from executing this these again and again.
  76. if (!goog.i18n.currency.tier2Enabled_) {
  77. for (var key in goog.i18n.currency.CurrencyInfoTier2) {
  78. goog.i18n.currency.CurrencyInfo[key] =
  79. goog.i18n.currency.CurrencyInfoTier2[key];
  80. }
  81. goog.i18n.currency.tier2Enabled_ = true;
  82. }
  83. };
  84. /**
  85. * Deprecated.
  86. * Global currency pattern always uses ISO-4217 currency code as prefix. Local
  87. * currency sign is added if it is different from currency code. Each currency
  88. * is unique in this form. The negative side is that ISO code looks weird in
  89. * some countries as people normally do not use it. Local currency sign
  90. * alleviates the problem, but also makes it a little verbose.
  91. *
  92. * @param {string} currencyCode ISO-4217 3-letter currency code.
  93. * @return {string} Global currency pattern string for given currency.
  94. * @deprecated Format numbers using {@link goog.i18n.NumberFormat} with
  95. * {@link goog.i18n.NumberFormat.Format.CURRENCY} and
  96. * {@link goog.i18n.NumberFormat.CurrencyStyle.GLOBAL}
  97. */
  98. goog.i18n.currency.getGlobalCurrencyPattern = function(currencyCode) {
  99. var info = goog.i18n.currency.CurrencyInfo[currencyCode];
  100. var patternNum = info[0];
  101. if (currencyCode == info[1]) {
  102. return goog.i18n.currency.getCurrencyPattern_(patternNum, info[1]);
  103. }
  104. return currencyCode + ' ' +
  105. goog.i18n.currency.getCurrencyPattern_(patternNum, info[1]);
  106. };
  107. /**
  108. * Return global currency sign string for those applications
  109. * that want to handle currency sign themselves.
  110. *
  111. * @param {string} currencyCode ISO-4217 3-letter currency code.
  112. * @return {string} Global currency sign for given currency.
  113. */
  114. goog.i18n.currency.getGlobalCurrencySign = function(currencyCode) {
  115. var info = goog.i18n.currency.CurrencyInfo[currencyCode];
  116. return (currencyCode == info[1]) ? currencyCode :
  117. currencyCode + ' ' + info[1];
  118. };
  119. /**
  120. * Deprecated.
  121. * Local currency pattern is the most frequently used pattern in currency's
  122. * native region. It does not care about how it is distinguished from other
  123. * currencies.
  124. *
  125. * @param {string} currencyCode ISO-4217 3-letter currency code.
  126. * @return {string} Local currency pattern string for given currency.
  127. * @deprecated Format numbers using {@link goog.i18n.NumberFormat} with
  128. * {@link goog.i18n.NumberFormat.Format.CURRENCY} and
  129. * {@link goog.i18n.NumberFormat.CurrencyStyle.LOCAL}
  130. */
  131. goog.i18n.currency.getLocalCurrencyPattern = function(currencyCode) {
  132. var info = goog.i18n.currency.CurrencyInfo[currencyCode];
  133. return goog.i18n.currency.getCurrencyPattern_(info[0], info[1]);
  134. };
  135. /**
  136. * Returns local currency sign string for those applications that need to
  137. * handle currency sign separately.
  138. *
  139. * @param {string} currencyCode ISO-4217 3-letter currency code.
  140. * @return {string} Local currency sign for given currency.
  141. */
  142. goog.i18n.currency.getLocalCurrencySign = function(currencyCode) {
  143. return goog.i18n.currency.CurrencyInfo[currencyCode][1];
  144. };
  145. /**
  146. * Deprecated.
  147. * Portable currency pattern is a compromise between local and global. It is
  148. * not a mere blend or mid-way between the two. Currency sign is chosen so that
  149. * it looks familiar to native users. It also has enough information to
  150. * distinguish itself from other popular currencies in its native region.
  151. * In this pattern, currency sign symbols that has availability problem in
  152. * popular fonts are also avoided.
  153. *
  154. * @param {string} currencyCode ISO-4217 3-letter currency code.
  155. * @return {string} Portable currency pattern string for given currency.
  156. * @deprecated Format numbers using {@link goog.i18n.NumberFormat} with
  157. * {@link goog.i18n.NumberFormat.Format.CURRENCY} and
  158. * {@link goog.i18n.NumberFormat.CurrencyStyle.PORTABLE}
  159. */
  160. goog.i18n.currency.getPortableCurrencyPattern = function(currencyCode) {
  161. var info = goog.i18n.currency.CurrencyInfo[currencyCode];
  162. return goog.i18n.currency.getCurrencyPattern_(info[0], info[2]);
  163. };
  164. /**
  165. * Return portable currency sign string for those applications that need to
  166. * handle currency sign themselves.
  167. *
  168. * @param {string} currencyCode ISO-4217 3-letter currency code.
  169. * @return {string} Portable currency sign for given currency.
  170. */
  171. goog.i18n.currency.getPortableCurrencySign = function(currencyCode) {
  172. return goog.i18n.currency.CurrencyInfo[currencyCode][2];
  173. };
  174. /**
  175. * This function returns the default currency sign's position. Some applications
  176. * may want to handle currency sign and currency amount separately. This
  177. * function can be used in such situations to correctly position the currency
  178. * sign relative to the amount.
  179. *
  180. * Use {@link goog.i18n.NumberFormat#isCurrencyCodeBeforeValue} for a locale
  181. * aware version of this API (recommended). isPrefixSignPosition() returns the
  182. * default currency sign's position in the currency's default locale (e.g. 'en'
  183. * for 'USD'), but most commonly the position is needed for the locale in which
  184. * the number is going to be displayed. For example, in 'fr' 10.10 USD would be
  185. * displayed as '10,10 $'.
  186. *
  187. * @param {string} currencyCode ISO-4217 3-letter currency code.
  188. * @return {boolean} true if currency should be positioned before amount field.
  189. */
  190. goog.i18n.currency.isPrefixSignPosition = function(currencyCode) {
  191. return (goog.i18n.currency.CurrencyInfo[currencyCode][0] &
  192. goog.i18n.currency.POSITION_FLAG_) == 0;
  193. };
  194. /**
  195. * This function constructs the currency pattern. Currency sign is provided. The
  196. * pattern information is encoded in patternNum.
  197. *
  198. * @param {number} patternNum Encoded pattern number that has
  199. * currency pattern information.
  200. * @param {string} sign The currency sign that will be used in pattern.
  201. * @return {string} currency pattern string.
  202. * @private
  203. */
  204. goog.i18n.currency.getCurrencyPattern_ = function(patternNum, sign) {
  205. var strParts = ['#,##0'];
  206. var precision = patternNum & goog.i18n.currency.PRECISION_MASK_;
  207. if (precision > 0) {
  208. strParts.push('.');
  209. for (var i = 0; i < precision; i++) {
  210. strParts.push('0');
  211. }
  212. }
  213. if ((patternNum & goog.i18n.currency.POSITION_FLAG_) == 0) {
  214. strParts.unshift(
  215. (patternNum & goog.i18n.currency.SPACE_FLAG_) ? "' " : "'");
  216. strParts.unshift(sign);
  217. strParts.unshift("'");
  218. } else {
  219. strParts.push(
  220. (patternNum & goog.i18n.currency.SPACE_FLAG_) ? " '" : "'", sign, "'");
  221. }
  222. return strParts.join('');
  223. };
  224. /**
  225. * Modify currency pattern string by adjusting precision for given currency.
  226. * Standard currency pattern will have 2 digit after decimal point.
  227. * Examples:
  228. * $#,##0.00 -> $#,##0 (precision == 0)
  229. * $#,##0.00 -> $#,##0.0 (precision == 1)
  230. * $#,##0.00 -> $#,##0.000 (precision == 3)
  231. *
  232. * @param {string} pattern currency pattern string.
  233. * @param {string} currencyCode 3-letter currency code.
  234. * @return {string} modified currency pattern string.
  235. */
  236. goog.i18n.currency.adjustPrecision = function(pattern, currencyCode) {
  237. var strParts = ['0'];
  238. var info = goog.i18n.currency.CurrencyInfo[currencyCode];
  239. var precision = info[0] & goog.i18n.currency.PRECISION_MASK_;
  240. if (precision > 0) {
  241. strParts.push('.');
  242. for (var i = 0; i < precision; i++) {
  243. strParts.push('0');
  244. }
  245. }
  246. return pattern.replace(/0.00/g, strParts.join(''));
  247. };
  248. /**
  249. * Tier 1 currency information.
  250. *
  251. * The first number in the array is a combination of the precision mask and
  252. * other flags. The precision mask indicates how many decimal places to show for
  253. * the currency. Valid values are [0..7]. The position flag indicates whether
  254. * the currency sign should be positioned after the number. Valid values are 0
  255. * (before the number) or 16 (after the number). The space flag indicates
  256. * whether a space should be inserted between the currency sign and number.
  257. * Valid values are 0 (no space) and 32 (space).
  258. *
  259. * The number in the array is calculated by adding together the mask and flag
  260. * values. For example:
  261. *
  262. * 0: no precision (0), currency sign first (0), no space (0)
  263. * 2: two decimals precision (2), currency sign first (0), no space (0)
  264. * 18: two decimals precision (2), currency sign last (16), no space (0)
  265. * 50: two decimals precision (2), currency sign last (16), space (32)
  266. *
  267. * It's not recommended to read this data directly. Format numbers using
  268. * {@link goog.i18n.NumberFormat} with
  269. * {@link goog.i18n.NumberFormat.Format.CURRENCY} instead.
  270. *
  271. * @const {!Object<!Array<?>>}
  272. */
  273. goog.i18n.currency.CurrencyInfo = {
  274. 'AED': [2, 'dh', '\u062f.\u0625.', 'DH'],
  275. 'ALL': [0, 'Lek', 'Lek'],
  276. 'AUD': [2, '$', 'AU$'],
  277. 'BDT': [2, '\u09F3', 'Tk'],
  278. 'BGN': [2, 'lev', 'lev'],
  279. 'BRL': [2, 'R$', 'R$'],
  280. 'CAD': [2, '$', 'C$'],
  281. 'CDF': [2, 'FrCD', 'CDF'],
  282. 'CHF': [2, 'CHF', 'CHF'],
  283. 'CLP': [0, '$', 'CL$'],
  284. 'CNY': [2, '¥', 'RMB¥'],
  285. 'COP': [32, '$', 'COL$'],
  286. 'CRC': [0, '\u20a1', 'CR\u20a1'],
  287. 'CZK': [50, 'K\u010d', 'K\u010d'],
  288. 'DKK': [50, 'kr.', 'kr.'],
  289. 'DOP': [2, 'RD$', 'RD$'],
  290. 'EGP': [2, '£', 'LE'],
  291. 'ETB': [2, 'Birr', 'Birr'],
  292. 'EUR': [2, '€', '€'],
  293. 'GBP': [2, '£', 'GB£'],
  294. 'HKD': [2, '$', 'HK$'],
  295. 'HRK': [2, 'kn', 'kn'],
  296. 'HUF': [34, 'Ft', 'Ft'],
  297. 'IDR': [0, 'Rp', 'Rp'],
  298. 'ILS': [34, '\u20AA', 'IL\u20AA'],
  299. 'INR': [2, '\u20B9', 'Rs'],
  300. 'IRR': [0, 'Rial', 'IRR'],
  301. 'ISK': [0, 'kr', 'kr'],
  302. 'JMD': [2, '$', 'JA$'],
  303. 'JPY': [0, '¥', 'JP¥'],
  304. 'KRW': [0, '\u20A9', 'KR₩'],
  305. 'LKR': [2, 'Rs', 'SLRs'],
  306. 'LTL': [2, 'Lt', 'Lt'],
  307. 'MNT': [0, '\u20AE', 'MN₮'],
  308. 'MVR': [2, 'Rf', 'MVR'],
  309. 'MXN': [2, '$', 'Mex$'],
  310. 'MYR': [2, 'RM', 'RM'],
  311. 'NOK': [50, 'kr', 'NOkr'],
  312. 'PAB': [2, 'B/.', 'B/.'],
  313. 'PEN': [2, 'S/.', 'S/.'],
  314. 'PHP': [2, '\u20B1', 'PHP'],
  315. 'PKR': [0, 'Rs', 'PKRs.'],
  316. 'PLN': [50, 'z\u0142', 'z\u0142'],
  317. 'RON': [2, 'RON', 'RON'],
  318. 'RSD': [0, 'din', 'RSD'],
  319. 'RUB': [50, '\u20bd', 'RUB'],
  320. 'SAR': [2, 'Rial', 'Rial'],
  321. 'SEK': [50, 'kr', 'kr'],
  322. 'SGD': [2, '$', 'S$'],
  323. 'THB': [2, '\u0e3f', 'THB'],
  324. 'TRY': [2, 'TL', 'YTL'],
  325. 'TWD': [2, 'NT$', 'NT$'],
  326. 'TZS': [0, 'TSh', 'TSh'],
  327. 'UAH': [2, 'грн.', 'UAH'],
  328. 'USD': [2, '$', 'US$'],
  329. 'UYU': [2, '$', '$U'],
  330. 'VND': [48, '\u20AB', 'VN\u20AB'],
  331. 'YER': [0, 'Rial', 'Rial'],
  332. 'ZAR': [2, 'R', 'ZAR']
  333. };
  334. /**
  335. * Tier 2 currency information.
  336. *
  337. * It's not recommended to read this data directly. Format numbers using
  338. * {@link goog.i18n.NumberFormat} with
  339. * {@link goog.i18n.NumberFormat.Format.CURRENCY} instead.
  340. *
  341. * @const {!Object<!Array<?>>}
  342. */
  343. goog.i18n.currency.CurrencyInfoTier2 = {
  344. 'AFN': [48, 'Af.', 'AFN'],
  345. 'AMD': [32, 'Dram', 'dram'],
  346. 'ANG': [2, 'NAf.', 'ANG'],
  347. 'AOA': [2, 'Kz', 'Kz'],
  348. 'ARS': [34, '$', 'AR$'],
  349. 'AWG': [2, 'Afl.', 'Afl.'],
  350. 'AZN': [34, '\u20bc', 'AZN'],
  351. 'BAM': [2, 'KM', 'KM'],
  352. 'BBD': [2, '$', 'Bds$'],
  353. 'BHD': [3, 'din', 'din'],
  354. 'BIF': [0, 'FBu', 'FBu'],
  355. 'BMD': [2, '$', 'BD$'],
  356. 'BND': [2, '$', 'B$'],
  357. 'BOB': [2, 'Bs', 'Bs'],
  358. 'BSD': [2, '$', 'BS$'],
  359. 'BTN': [2, 'Nu.', 'Nu.'],
  360. 'BWP': [2, 'P', 'pula'],
  361. 'BYR': [48, 'p.', 'BYR'],
  362. 'BZD': [2, '$', 'BZ$'],
  363. 'CUC': [1, '$', 'CUC$'],
  364. 'CUP': [2, '$', 'CU$'],
  365. 'CVE': [2, 'CVE', 'Esc'],
  366. 'DJF': [0, 'Fdj', 'Fdj'],
  367. 'DZD': [2, 'din', 'din'],
  368. 'ERN': [2, 'Nfk', 'Nfk'],
  369. 'FJD': [2, '$', 'FJ$'],
  370. 'FKP': [2, '£', 'FK£'],
  371. 'GEL': [2, 'GEL', 'GEL'],
  372. 'GHS': [2, 'GHS', 'GHS'],
  373. 'GIP': [2, '£', 'GI£'],
  374. 'GMD': [2, 'GMD', 'GMD'],
  375. 'GNF': [0, 'FG', 'FG'],
  376. 'GTQ': [2, 'Q', 'GTQ'],
  377. 'GYD': [0, '$', 'GY$'],
  378. 'HNL': [2, 'L', 'HNL'],
  379. 'HTG': [2, 'HTG', 'HTG'],
  380. 'IQD': [0, 'din', 'IQD'],
  381. 'JOD': [3, 'din', 'JOD'],
  382. 'KES': [2, 'Ksh', 'Ksh'],
  383. 'KGS': [2, 'KGS', 'KGS'],
  384. 'KHR': [2, 'Riel', 'KHR'],
  385. 'KMF': [0, 'CF', 'KMF'],
  386. 'KPW': [0, '\u20A9KP', 'KPW'],
  387. 'KWD': [3, 'din', 'KWD'],
  388. 'KYD': [2, '$', 'KY$'],
  389. 'KZT': [2, '\u20B8', 'KZT'],
  390. 'LAK': [0, '\u20AD', '\u20AD'],
  391. 'LBP': [0, 'L£', 'LBP'],
  392. 'LRD': [2, '$', 'L$'],
  393. 'LSL': [2, 'LSL', 'LSL'],
  394. 'LYD': [3, 'din', 'LD'],
  395. 'MAD': [2, 'dh', 'MAD'],
  396. 'MDL': [2, 'MDL', 'MDL'],
  397. 'MGA': [0, 'Ar', 'MGA'],
  398. 'MKD': [2, 'din', 'MKD'],
  399. 'MMK': [0, 'K', 'MMK'],
  400. 'MOP': [2, 'MOP', 'MOP$'],
  401. 'MRO': [0, 'MRO', 'MRO'],
  402. 'MUR': [0, 'MURs', 'MURs'],
  403. 'MWK': [2, 'MWK', 'MWK'],
  404. 'MZN': [2, 'MTn', 'MTn'],
  405. 'NAD': [2, '$', 'N$'],
  406. 'NGN': [2, '\u20A6', 'NG\u20A6'],
  407. 'NIO': [2, 'C$', 'C$'],
  408. 'NPR': [2, 'Rs', 'NPRs'],
  409. 'NZD': [2, '$', 'NZ$'],
  410. 'OMR': [3, 'Rial', 'OMR'],
  411. 'PGK': [2, 'PGK', 'PGK'],
  412. 'PYG': [16, 'Gs.', 'PYG'],
  413. 'QAR': [2, 'Rial', 'QR'],
  414. 'RWF': [0, 'RF', 'RF'],
  415. 'SBD': [2, '$', 'SI$'],
  416. 'SCR': [2, 'SCR', 'SCR'],
  417. 'SDG': [2, 'SDG', 'SDG'],
  418. 'SHP': [2, '£', 'SH£'],
  419. 'SLL': [0, 'SLL', 'SLL'],
  420. 'SOS': [0, 'SOS', 'SOS'],
  421. 'SRD': [2, '$', 'SR$'],
  422. 'SSP': [2, '£', 'SSP'],
  423. 'STD': [0, 'Db', 'Db'],
  424. 'SYP': [0, '£', 'SY£'],
  425. 'SZL': [2, 'SZL', 'SZL'],
  426. 'TJS': [2, 'Som', 'TJS'],
  427. 'TND': [3, 'din', 'DT'],
  428. 'TOP': [2, 'T$', 'T$'],
  429. 'TTD': [2, '$', 'TT$'],
  430. 'UGX': [0, 'UGX', 'UGX'],
  431. 'UZS': [0, 'so\u02bcm', 'UZS'],
  432. 'VEF': [2, 'Bs', 'Bs'],
  433. 'VUV': [0, 'VUV', 'VUV'],
  434. 'WST': [2, 'WST', 'WST'],
  435. 'XAF': [0, 'FCFA', 'FCFA'],
  436. 'XCD': [2, '$', 'EC$'],
  437. 'XOF': [0, 'CFA', 'CFA'],
  438. 'XPF': [48, 'FCFP', 'FCFP'],
  439. 'ZMW': [0, 'ZMW', 'ZMW'],
  440. 'ZWD': [0, '$', 'Z$']
  441. };