Coder Social home page Coder Social logo

yamadapc / js-written-number Goto Github PK

View Code? Open in Web Editor NEW
362.0 12.0 124.0 230 KB

Convert numbers to words - their written form

Home Page: https://yamadapc.github.io/js-written-number

License: MIT License

JavaScript 100.00%
javascript language convert-numbers

js-written-number's Introduction

js-written-number

Gitter Build Status Code Climate Coverage Status Dependency Status devDependency Status Analytics npm downloads per month npm version


Convert numbers to words - their written form.

Install

With npm:

npm install --save written-number

With bower:

bower install written-number

Usage

var writtenNumber = require('written-number');
writtenNumber(1234); // => 'one thousand two hundred and thirty-four'

writtenNumber.defaults.lang = 'es';
writtenNumber(4758); // => 'cuatro mil setecientos cincuenta y ocho'

writtenNumber(1234, {lang: 'fr'});   // => 'mille deux cent trente-quatre'
writtenNumber(1234, {lang: 'es'});   // => 'mil doscientos treinta y cuatro'
writtenNumber(1234, {lang: 'az'});   // => 'min iki yüz otuz dörd'
writtenNumber(1234, {lang: 'pt'});   // => 'mil duzentos e trinta e quatro'
writtenNumber(1234, {lang: 'ar'});   // => 'ألف ومائتان وأربعة وثلاثون'
writtenNumber(1234, {lang: 'eo'});   // => 'mil ducent tridek kvar'
writtenNumber(1234, {lang: 'vi'});   // => 'một ngàn hai trăm và ba mươi bốn'
writtenNumber(1234, {lang: 'uk'});   // => 'одна тисяча двісті тридцять чотири'
writtenNumber(1234, {lang: 'id'});   // => 'seribu dua ratus tiga puluh empat'

Options

  • noAnd - Defaults to false. Determines whether to use a separator. The separator is internationalized.
  • lang - Could be string or object. Defaults to 'en'. Determines which language to use. An i18n configuration object may be passed to support external language definitions.

Currently supported languages are:

Language lang
English en
Portuguese (Brazil) pt
Portuguese (Portugal) ptPT
Spanish es
French fr
Esperanto eo
Vietnamese vi
Arabic ar
Azerbaijan az
Turkish tr
English (Indian) enIndian
Ukrainian uk
Indonesian id
Russian ru

Contributing

Configure your own language

Each language has its own unique grammar exceptions. You can create your own language.json file in the folder "i18n" and give writtenNumber support for it. I don't think the current scheme and logic cover all the cases, but may be cover some.

The following parameters have been used for the currently available languages:

Language parameters

Parameter Type Description Examples
useLongScale boolean Indicates if it uses long or short scale. This differs the meaning of the words billion, trillion and so on.
baseSeparator string Separates the base cardinal numbers. 29 -> twenty-eight. Spanish uses the connector " y "
unitSeparator string Separates the units from the last base cardinal numbers. 1234 -> one thousand two hundred and thirty-four
allSeparator string Separates all cardinals, not only the last one. 1125 -> ألف ومائة وخمسة وعشرون
base Object Base cardinals numbers. Numbers that have unique names and are used to build others.
alternativeBase Object Alternative versions of base cardinals numbers for usage with specific units. These bases will be treated as an extension for the default base. "alternativeBase": { "feminine": {"1":"одна","2":"дві"} }
units Array A list of number units (string or Object). Gives support to singular, dual an plural units. Check the Object parameters below.
unitExceptions Object Sometimes grammar exceptions affect the base cardinal joined to the unit. You can set specific exceptions to any base cardinal number. Converting 1232000 in Spanish: Without Exception (Wrong): -> uno millón doscientos treinta y dos mil With Exception: -> un millón doscientos treinta y dos mil

Units parameters

A unit can be:

  • A simple string. e.g. "hundred"
  • An Object with multiple parameters:
Unit parameter Description e.g. of languages
singular One element. All
dual Two elements. ar
plural Two or more elements. (or 3 or more) All
few Between 2 and 4 including. uk
useAlternativeBase Overwrites default base. uk
useBaseInstead Use the base cardinal number instead. es,hu,pt
useBaseException Specify with which unit (1 to 9) you don't want to use the base, and instead use the regular behavior. es,hu,pt
avoidPrefixException Units not using the base cardinal number prefix for unit 1. id,tr,it
avoidInNumberPlural Units not using the plural form with trailing numbers other than 0. fr
restrictedPlural Plural only for 3 to 10. Singular if >= 11. ar
useSingularEnding Use singular form for numbers ending with 1. uk
useFewEnding Use few form for numbers ending with 2, 3 or 4. uk
avoidEndingRules Plural form used instead of useSingularEnding and useFewEnding uk

Versioning

Do your changes and submit a PR. If you've write access and want to bump the version, run mversion [major|minor|patch] -m. That'll bump both bower.json and package.json.

License

This code is licensed under the MIT license for Pedro Tacla Yamada. For more information, please refer to the LICENSE file.

js-written-number's People

Contributors

asmarques avatar beingmohit avatar bjrmatos avatar costava avatar dannyfeliz avatar davidnguyen11 avatar dejurin avatar dependabot[bot] avatar faridbabayev001 avatar forzagreen avatar gabrielbull avatar greenkeeperio-bot avatar khanhnk avatar loick-michard avatar lucascdsilva avatar maxiruani avatar mlallena avatar mrofi avatar noehedde avatar ovr avatar p3x-robot avatar sytolk avatar taras-ua avatar tombyrer avatar vtrifonov avatar yamadapc avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

js-written-number's Issues

"uno mil" -> "un mil"

Hello!

There is a small issue in spanish because it says "uno mil" instead of "un mil".

For example:
https://jsfiddle.net/zarza/un4swL1h/3/

Result:
catorce millones novecientos ochenta y uno mil cuatrocientos cincuenta y seis

And it should be just like NumberFormat in PHP:
catorce millones nove­cientos ochenta y un mil cuatrocientos cincuenta y seis

PHP code:

$formatter = new \NumberFormatter('es', \NumberFormatter::SPELLOUT);
echo $formatter->format(14981456) . "\n";

Any idea of how can we improve this? Currently I'm doing a simple replace from "uno mil" to "un mil".

Negative numbers are formatted incorrectly

The code:

console.log(writtenNumber(-1))
console.log(writtenNumber(-2))
console.log(writtenNumber(-3))

console.log(writtenNumber(-10))
console.log(writtenNumber(-20))
console.log(writtenNumber(-30))

console.log(writtenNumber(-100))
console.log(writtenNumber(-200))
console.log(writtenNumber(-300))

console.log(writtenNumber(-1000))
console.log(writtenNumber(-2000))
console.log(writtenNumber(-3000))

outputs the following:

"undefined-nine"
"undefined-eight"
"undefined-seven"

undefined
undefined
undefined

undefined
undefined
undefined

undefined
undefined
undefined

Add support to russian

{
	"useLongScale": false,
	"baseSeparator": " ",
        "unitSeparator": "",
	"base": {
		"0": "ноль",
		"1": "один",
		"2": "два",
		"3": "три",
		"4": "четыре",
		"5": "пять",
		"6": "шесть",
		"7": "семь",
		"8": "восемь",
		"9": "девять",
		"10": "десять",
		"11": "одиннадцать",
		"12": "двенадцать",
		"13": "тринадцать",
		"14": "четырнадцать",
		"15": "пятнадцать",
		"16": "шестнадцать",
		"17": "семнадцать",
		"18": "восемнадцать",
		"19": "девятнадцать",
		"20": "двадцать",
		"30": "тридцать",
		"40": "сорок",
		"50": "пятьдесят",
		"60": "шестьдесят",
		"70": "семьдесят",
		"80": "восемьдесят",
		"90": "девяносто",
		"100": "сто",
		"200": "двести",
		"300": "триста",
		"400": "четыреста",
		"500": "пятьсот",
		"600": "шестьсот",
		"700": "семьсот",
		"800": "восемьсот",
		"900": "девятьсот"
	},
	"alternativeBase": {
		"feminine": {
			"1": "одна",
			"2": "две"
		}
	},
	"units": [{
			"useBaseInstead": true,
			"useBaseException": []
		},
		{
			"singular": "тысяча",
			"few": "тысячи",
			"plural": "тысяч",
			"useAlternativeBase": "feminine",
			"useSingularEnding": true,
			"useFewEnding": true,
			"avoidEndingRules": [11, 12, 13, 14, 111, 112, 113, 114, 211, 212, 213, 214, 311, 312, 313, 314, 411, 412, 413, 414, 511, 512, 513, 514, 611, 612, 613, 614, 711, 712, 713, 714, 811, 812, 813, 814, 911, 912, 913, 914]
		},
		{
			"singular": "миллион",
			"few": "миллионы",
			"plural": "миллионов",
			"useSingularEnding": true,
			"useFewEnding": true,
			"avoidEndingRules": [11, 12, 13, 14, 111, 112, 113, 114, 211, 212, 213, 214, 311, 312, 313, 314, 411, 412, 413, 414, 511, 512, 513, 514, 611, 612, 613, 614, 711, 712, 713, 714, 811, 812, 813, 814, 911, 912, 913, 914]
		},
		{
			"singular": "миллиард",
			"few": "миллиарды",
			"plural": "миллиардов",
			"useSingularEnding": true,
			"useFewEnding": true,
			"avoidEndingRules": [11, 12, 13, 14, 111, 112, 113, 114, 211, 212, 213, 214, 311, 312, 313, 314, 411, 412, 413, 414, 511, 512, 513, 514, 611, 612, 613, 614, 711, 712, 713, 714, 811, 812, 813, 814, 911, 912, 913, 914]
		},
		{
			"singular": "триллион",
			"few": "триллионы",
			"plural": "триллионов",
			"useSingularEnding": true,
			"useFewEnding": true,
			"avoidEndingRules": [11, 12, 13, 14, 111, 112, 113, 114, 211, 212, 213, 214, 311, 312, 313, 314, 411, 412, 413, 414, 511, 512, 513, 514, 611, 612, 613, 614, 711, 712, 713, 714, 811, 812, 813, 814, 911, 912, 913, 914]
		},
		{
			"singular": "квадрильон",
			"few": "квадриллион",
			"plural": "квадрилон",
			"useSingularEnding": true,
			"useFewEnding": true,
			"avoidEndingRules": [11, 12, 13, 14, 111, 112, 113, 114, 211, 212, 213, 214, 311, 312, 313, 314, 411, 412, 413, 414, 511, 512, 513, 514, 611, 612, 613, 614, 711, 712, 713, 714, 811, 812, 813, 814, 911, 912, 913, 914]
		},
		{
			"singular": "квинтиллион",
			"few": "квинтиллиона",
			"plural": "квинтильонов",
			"useSingularEnding": true,
			"useFewEnding": true,
			"avoidEndingRules": [11, 12, 13, 14, 111, 112, 113, 114, 211, 212, 213, 214, 311, 312, 313, 314, 411, 412, 413, 414, 511, 512, 513, 514, 611, 612, 613, 614, 711, 712, 713, 714, 811, 812, 813, 814, 911, 912, 913, 914]
		},
		{
			"singular": "секстиллионов",
			"few": "секстильоны",
			"plural": "секстиллионов",
			"useSingularEnding": true,
			"useFewEnding": true,
			"avoidEndingRules": [11, 12, 13, 14, 111, 112, 113, 114, 211, 212, 213, 214, 311, 312, 313, 314, 411, 412, 413, 414, 511, 512, 513, 514, 611, 612, 613, 614, 711, 712, 713, 714, 811, 812, 813, 814, 911, 912, 913, 914]
		},
		{
			"singular": "септиллион",
			"few": "септиллионы",
			"plural": "септиллионов",
			"useSingularEnding": true,
			"useFewEnding": true,
			"avoidEndingRules": [11, 12, 13, 14, 111, 112, 113, 114, 211, 212, 213, 214, 311, 312, 313, 314, 411, 412, 413, 414, 511, 512, 513, 514, 611, 612, 613, 614, 711, 712, 713, 714, 811, 812, 813, 814, 911, 912, 913, 914]
		},
		{
			"singular": "октиллион",
			"few": "октиллионы",
			"plural": "октиллионов",
			"useSingularEnding": true,
			"useFewEnding": true,
			"avoidEndingRules": [11, 12, 13, 14, 111, 112, 113, 114, 211, 212, 213, 214, 311, 312, 313, 314, 411, 412, 413, 414, 511, 512, 513, 514, 611, 612, 613, 614, 711, 712, 713, 714, 811, 812, 813, 814, 911, 912, 913, 914]
		},
		{
			"singular": "нониллион",
			"few": "нониллионы",
			"plural": "нониллионов",
			"useSingularEnding": true,
			"useFewEnding": true,
			"avoidEndingRules": [11, 12, 13, 14, 111, 112, 113, 114, 211, 212, 213, 214, 311, 312, 313, 314, 411, 412, 413, 414, 511, 512, 513, 514, 611, 612, 613, 614, 711, 712, 713, 714, 811, 812, 813, 814, 911, 912, 913, 914]
		},
		{
			"singular": "дециллион",
			"few": "дециллионы",
			"plural": "дециллионов",
			"useSingularEnding": true,
			"useFewEnding": true,
			"avoidEndingRules": [11, 12, 13, 14, 111, 112, 113, 114, 211, 212, 213, 214, 311, 312, 313, 314, 411, 412, 413, 414, 511, 512, 513, 514, 611, 612, 613, 614, 711, 712, 713, 714, 811, 812, 813, 814, 911, 912, 913, 914]
		},
		{
			"singular": "ундециллион",
			"few": "ундециллионы",
			"plural": "ундециллионив",
			"useSingularEnding": true,
			"useFewEnding": true,
			"avoidEndingRules": [11, 12, 13, 14, 111, 112, 113, 114, 211, 212, 213, 214, 311, 312, 313, 314, 411, 412, 413, 414, 511, 512, 513, 514, 611, 612, 613, 614, 711, 712, 713, 714, 811, 812, 813, 814, 911, 912, 913, 914]
		},
		{
			"singular": "дуодециллион",
			"few": "дуодециллионы",
			"plural": "дуодециллионив",
			"useSingularEnding": true,
			"useFewEnding": true,
			"avoidEndingRules": [11, 12, 13, 14, 111, 112, 113, 114, 211, 212, 213, 214, 311, 312, 313, 314, 411, 412, 413, 414, 511, 512, 513, 514, 611, 612, 613, 614, 711, 712, 713, 714, 811, 812, 813, 814, 911, 912, 913, 914]
		},
		{
			"singular": "тредециллион",
			"few": "тредециллионы",
			"plural": "тредециллионив",
			"useSingularEnding": true,
			"useFewEnding": true,
			"avoidEndingRules": [11, 12, 13, 14, 111, 112, 113, 114, 211, 212, 213, 214, 311, 312, 313, 314, 411, 412, 413, 414, 511, 512, 513, 514, 611, 612, 613, 614, 711, 712, 713, 714, 811, 812, 813, 814, 911, 912, 913, 914]
		},
		{
			"singular": "кватуордециллион",
			"few": "кватуордециллионы",
			"plural": "кватуордециллионив",
			"useSingularEnding": true,
			"useFewEnding": true,
			"avoidEndingRules": [11, 12, 13, 14, 111, 112, 113, 114, 211, 212, 213, 214, 311, 312, 313, 314, 411, 412, 413, 414, 511, 512, 513, 514, 611, 612, 613, 614, 711, 712, 713, 714, 811, 812, 813, 814, 911, 912, 913, 914]
		},
		{
			"singular": "квиндециллион",
			"few": "квиндециллионы",
			"plural": "квиндециллионив",
			"useSingularEnding": true,
			"useFewEnding": true,
			"avoidEndingRules": [11, 12, 13, 14, 111, 112, 113, 114, 211, 212, 213, 214, 311, 312, 313, 314, 411, 412, 413, 414, 511, 512, 513, 514, 611, 612, 613, 614, 711, 712, 713, 714, 811, 812, 813, 814, 911, 912, 913, 914]
		}
	],
	"unitExceptions": []
}

Do not round decimal number

Hey, guys.

How can I avoid rounding up numbers?
Here: 342 877,50
I expect: trezentos e quarenta e dois mil oitocentos e setenta e sete e cinquenta cêntimos
I got: trezentos e quarenta e dois mil oitocentos e setenta e oito

Thanks

Add a way not to include all locales

There should be a means of not including all locales.

A very simple solution would be to move the logic to lib/core and keep lib/index including all locales, so people would be able to manually require just the logic and the locales they'll use:

import writtenNumber from 'written-number/lib/core';
import writtenNumberEn from 'written-number/lib/i18n/en';
// ...

Adding Persian

Hi guys,
I was trying to add Persian(Farsi) for this library that I faced some problems , thought it's good to share them here so that I can figure out that do you have any solution for them or not.
First of all this is the json file I've created:


{
"useLongScale": false,
"baseSeparator": " و ",
"base": {
"0": "صفر",
"1": "یک",
"2": "دو",
"3": "سه",
"4": "چهار",
"5": "پنج",
"6": "شش",
"7": "هفت",
"8": "هشت",
"9": "نه",
"10": "ده",
"11": "یازده",
"12": "دوازده",
"13": "سیزده",
"14": "چهارده",
"15": "پانزده",
"16": "شانزده",
"17": "هفده",
"18": "هجده",
"19": "نوزده",
"20": "یست",
"30": "سی",
"40": "چهل",
"50": "پنجاه",
"60": "شصت",
"70": "هفتاد",
"80": "هشتاد",
"90": "نود",
"100": "صد",
"200": "دویست",
"300":"سی صد ",
"500":"پانصد صد ",
...
},
"units": [
"صد",
"هزار",
"میلیون",
"بیلیون"
],
"unitExceptions": [ ]
}


I was testing some random numbers like:
writtenNumber(1234, { lang: 'fa' }) // یک هزار دو صد و سی و چهار

This one has two issues .

1. In Persian we have exception for numbers 200 , 300 , 500, that they can not be made out of just mixing the number + the word "hundred" like: 2(two) + hundred or like 5(five) + hundred , they are special , but about others we can do such a think, like for 800 all we have to do is to mix the word "هشت" (or "eight" in English) with "صد" which stands for hundred.
So please help me resolve this ,how can I write some conditional statements for 200 , 300 , 500
What's the solution?

2. Second one is Separator issue , in Persian after every number we should have that Separator. But in this example after first number which is "یک هزار" (meaning one thousand) we don't see the Separator " و " even though after this first number that's OK and we see the Separator after every number which are that bold ones below and that italic one is actually the missing one which I described about:
یک هزار و دو صد و سی و چهار
How can I resolve this one too?

Thanks

1 fail in spanish

Hi, Very cleaver and simple approach. Thanks !
I was wondering if there is not an issue with 1 in Spanish. I'm not spanish but it seems that 1 would convert to "uno" but it converts to "un" instead.

  writtenNumber(1).should.equal('uno');

Regards !
Ant.

How to set `allSeparator` to empty?

I would like to remove space for all.
In my language don't use space for number & unit (Khmer Riel)

Ex: writtenNumber(1234); // => 'onethousandtwohundredthirtyfour'

Error with numbers above Number.MAX_SAFE_INTEGER

There is a loss of precision when converting numbers above Number.MAX_SAFE_INTEGER (9007199254740991).

writtenNumber(100000000000000002); 
// => 'one hundred quadrillion'

writtenNumber(100000000000000039); 
// => 'one hundred quadrillion thirty-two' ??

It would nice to be able to safely convert numbers above this limit.

Incorrect written number for hundred numbers without trailing numbers in Spanish

For:

writtenNumber(1101, { lang: "es" })
\\ it returns "mil ciento uno" -> CORRECT

for:

writtenNumber(1100, { lang: "es" })
\\ it returns "mil ciento" -> INCORRECT
\\ it should be "mil cien"

The solution is to modify the first unit for "es.json" language file to add "useBaseExceptionWhenNoTrailingNumbers" property:

{
      "singular": "ciento",
      "useBaseInstead": true,
      "useBaseException": [1],
      "useBaseExceptionWhenNoTrailingNumbers": true
}

14100 in portuguese

converting 14100 returns catorze mil cento, but it should return catorze mil e cem.
The same applies to anything ending in 100 (expect 100 itself). e.g 100100 is cem mil e cem.

I'm not really sure how to fix this.

Fractions and non-integer numbers

Neat lib, thanks for the clean & easy to scan code!

it('correctly converts numbers < 0', function() {
  writtenNumber(0.5).should.equal('half');
  writtenNumber('1/3').should.equal('a third'); // one third?
  writtenNumber('0.333333333').should.equal('a third'); // one third?
  writtenNumber('0.1').should.equal('a tenth'); // one tenth?
  writtenNumber('1/16').should.equal('a sixteenth');
});

Might be out of scope?

Cents

Is there a way of adding cent to words also?

Error with plural before "mille" (thousand) in French

Hello, thank you for this package, this is the most accurate I have seen for French numbers.

There is just one case that isn't handled correctly: the word "mille" (thousand) in french is a numeral adjective (same as "un", "deux", "trois", etc), which means that the word immediately before it shouldn't be plural (as opposed to "millions", "milliards" and following, which are common nouns).

e.g.

writtenNumber(201, { lang: "fr" }); // "deux cent un" ✅
writtenNumber(200000, { lang: "fr" }); // "deux cents mille" ❌ -> should be "deux cent mille" (same rule as 201)
writtenNumber(200000000, { lang: "fr" }); // "deux cents millions" ✅ (this is correct, "millions" is not a numeral adjective)

writtenNumber(81, { lang: "fr" }); // "quatre-vingt-un" ✅
writtenNumber(800000, { lang: "fr" }); // "quatre-vingts mille" ❌ -> should be "quatre-vingt mille" (similar to 81 rule, but no dash)
writtenNumber(800000000, { lang: "fr" }); // "quatre-vingts millions" ✅ (this is correct, "millions" is not a numeral adjective)

bower is not updated

Ciao!
How are you?
I know we should use webpack, but we have not moved to webpack and the Hungarian is not in bower.

Would you provide the Hungarian generated bower?

Thanks,
Patrik

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.