written-number-klis87
Version:
Convert numbers to words - their written form.
208 lines (174 loc) • 5.43 kB
JavaScript
;
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];
}