UNPKG

written-number-klis87

Version:

Convert numbers to words - their written form.

208 lines (174 loc) 5.43 kB
"use strict"; exports = module.exports = writtenNumber; var util = require("./util"); var languages = ["en", "es", "pt", "fr", "eo", "it", "vi", "tr", "uk"]; var i18n = { en: require("./i18n/en.json"), es: require("./i18n/es.json"), pt: require("./i18n/pt.json"), ptPT: require("./i18n/pt-PT.json"), fr: require("./i18n/fr.json"), eo: require("./i18n/eo.json"), it: require("./i18n/it.json"), vi: require("./i18n/vi.json"), tr: require("./i18n/tr.json"), hu: require("./i18n/hu.json"), enIndian: require("./i18n/en-indian.json"), uk: require("./i18n/uk.json") }; exports.i18n = i18n; var shortScale = [100]; for (var i = 1; i <= 16; i++) { shortScale.push(Math.pow(10, i * 3)); } var longScale = [100, 1000]; for (i = 1; i <= 15; i++) { longScale.push(Math.pow(10, i * 6)); } writtenNumber.defaults = { noAnd: false, alternativeBase: null, lang: "en" }; /** * Converts numbers to their written form. * * @param {Number} n The number to convert * @param {Object} [options] An object representation of the options * @return {String} writtenN The written form of `n` */ function writtenNumber(n, options) { options = options || {}; options = util.defaults(options, writtenNumber.defaults); if (n < 0) { return ""; } n = Math.round(+n); var language = typeof options.lang === "string" ? i18n[options.lang] : options.lang; if (!language) { if (languages.indexOf(writtenNumber.defaults.lang) < 0) { writtenNumber.defaults.lang = "en"; } language = i18n[writtenNumber.defaults.lang]; } var scale = language.useLongScale ? longScale : shortScale; var units = language.units; var unit; if (!(units instanceof Array)) { var rawUnits = units; units = []; scale = Object.keys(rawUnits); for (var i in scale) { units.push(rawUnits[scale[i]]); scale[i] = Math.pow(10, parseInt(scale[i])); } } var baseCardinals = language.base; var alternativeBaseCardinals = options.alternativeBase ? language.alternativeBase[options.alternativeBase] : {}; if (language.unitExceptions[n]) return language.unitExceptions[n]; if (alternativeBaseCardinals[n]) return alternativeBaseCardinals[n]; if (baseCardinals[n]) return baseCardinals[n]; if (n < 100) return handleSmallerThan100(n, language, unit, baseCardinals, alternativeBaseCardinals, options); var m = n % 100; var ret = []; if (m) { if ( options.noAnd && !(language.andException && language.andException[10]) ) { ret.push(writtenNumber(m, options)); } else { ret.push(language.unitSeparator + writtenNumber(m, options)); } } var firstSignificant; for (var i = 0, len = units.length; i < len; i++) { var r = Math.floor(n / scale[i]); var divideBy; if (i === len - 1) divideBy = 1000000; else divideBy = scale[i + 1] / scale[i]; r %= divideBy; unit = units[i]; if (!r) continue; firstSignificant = scale[i]; if (unit.useBaseInstead) { var shouldUseBaseException = unit.useBaseException.indexOf(r) > -1 && (unit.useBaseExceptionWhenNoTrailingNumbers ? i === 0 && ret.length : true); if (!shouldUseBaseException) { ret.push(alternativeBaseCardinals[r * scale[i]] || baseCardinals[r * scale[i]]); } else { ret.push(r > 1 && unit.plural ? unit.plural : unit.singular); } continue; } var str; if (typeof unit === "string") { str = unit; } else if (r === 1 || unit.useSingularEnding && r % 10 === 1 && (!unit.avoidEndingRules || unit.avoidEndingRules.indexOf(r) < 0)) { str = unit.singular; } else if (unit.few && (r > 1 && r < 5 || unit.useFewEnding && r % 10 > 1 && r % 10 < 5 && (!unit.avoidEndingRules || unit.avoidEndingRules.indexOf(r) < 0))) { str = unit.few; } else { str = unit.plural && (!unit.avoidInNumberPlural || !m) ? unit.plural : unit.singular; } if ( unit.avoidPrefixException && unit.avoidPrefixException.indexOf(r) > -1 ) { ret.push(str); continue; } var exception = language.unitExceptions[r]; var number = exception || writtenNumber( r, util.defaults( { // Languages with and exceptions need to set `noAnd` to false noAnd: !((language.andException && language.andException[r]) || unit.andException) && true, alternativeBase: unit.useAlternativeBase }, options ) ); n -= r * scale[i]; ret.push(number + " " + str); } var firstSignificantN = firstSignificant * Math.floor(n / firstSignificant); var rest = n - firstSignificantN; if ( language.andWhenTrailing && firstSignificant && 0 < rest && ret[0].indexOf(language.unitSeparator) !== 0 ) { ret = [ret[0], language.unitSeparator.replace(/\s+$/, "")].concat( ret.slice(1) ); } return ret.reverse().join(" "); } function handleSmallerThan100(n, language, unit, baseCardinals, alternativeBaseCardinals, options) { var dec = Math.floor(n / 10) * 10; unit = n - dec; if (unit) { return ( alternativeBaseCardinals[dec] || baseCardinals[dec] + language.baseSeparator + writtenNumber(unit, options) ); } return alternativeBaseCardinals[dec] || baseCardinals[dec]; }