mirror of
https://github.com/bblaz/num2words.git
synced 2025-12-06 14:52:25 +00:00
add indonesian ('id')
This commit is contained in:
@@ -27,6 +27,7 @@ from . import lang_LT
|
|||||||
from . import lang_LV
|
from . import lang_LV
|
||||||
from . import lang_PL
|
from . import lang_PL
|
||||||
from . import lang_RU
|
from . import lang_RU
|
||||||
|
from . import lang_ID
|
||||||
|
|
||||||
CONVERTER_CLASSES = {
|
CONVERTER_CLASSES = {
|
||||||
'en': lang_EN.Num2Word_EN(),
|
'en': lang_EN.Num2Word_EN(),
|
||||||
@@ -36,6 +37,7 @@ CONVERTER_CLASSES = {
|
|||||||
'fr_CH': lang_FR_CH.Num2Word_FR_CH(),
|
'fr_CH': lang_FR_CH.Num2Word_FR_CH(),
|
||||||
'de': lang_DE.Num2Word_DE(),
|
'de': lang_DE.Num2Word_DE(),
|
||||||
'es': lang_ES.Num2Word_ES(),
|
'es': lang_ES.Num2Word_ES(),
|
||||||
|
'id': lang_ID.Num2Word_ID(),
|
||||||
'lt': lang_LT.Num2Word_LT(),
|
'lt': lang_LT.Num2Word_LT(),
|
||||||
'lv': lang_LV.Num2Word_LV(),
|
'lv': lang_LV.Num2Word_LV(),
|
||||||
'pl': lang_PL.Num2Word_PL(),
|
'pl': lang_PL.Num2Word_PL(),
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ class Num2Word_Base(object):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def to_ordinal(value):
|
def to_ordinal(self, value):
|
||||||
return self.to_cardinal(value)
|
return self.to_cardinal(value)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
194
num2words/lang_ID.py
Normal file
194
num2words/lang_ID.py
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||||
|
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
|
||||||
|
|
||||||
|
# This library is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU Lesser General Public
|
||||||
|
# License as published by the Free Software Foundation; either
|
||||||
|
# version 2.1 of the License, or (at your option) any later version.
|
||||||
|
# This library is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
# Lesser General Public License for more details.
|
||||||
|
# You should have received a copy of the GNU Lesser General Public
|
||||||
|
# License along with this library; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
# MA 02110-1301 USA
|
||||||
|
|
||||||
|
class Num2Word_ID():
|
||||||
|
|
||||||
|
BASE = {0: [],
|
||||||
|
1: ["satu"],
|
||||||
|
2: ["dua"],
|
||||||
|
3: ["tiga"],
|
||||||
|
4: ["empat"],
|
||||||
|
5: ["lima"],
|
||||||
|
6: ["enam"],
|
||||||
|
7: ["tujuh"],
|
||||||
|
8: ["delapan"],
|
||||||
|
9: ["sembilan"]}
|
||||||
|
|
||||||
|
TENS_TO = {3: "ribu",
|
||||||
|
6: "juta",
|
||||||
|
9: "miliar",
|
||||||
|
12: "triliun",
|
||||||
|
15: "kuadriliun",
|
||||||
|
18: "kuantiliun",
|
||||||
|
21: "sekstiliun",
|
||||||
|
24: "septiliun",
|
||||||
|
27: "oktiliun",
|
||||||
|
30: "noniliun",
|
||||||
|
33: "desiliun"}
|
||||||
|
|
||||||
|
errmsg_floatord = "Cannot treat float number as ordinal"
|
||||||
|
errmsg_negord = "Cannot treat negative number as ordinal"
|
||||||
|
errmsg_toobig = "Too large"
|
||||||
|
max_num = 10**36
|
||||||
|
|
||||||
|
def split_by_koma(self, number):
|
||||||
|
return str(number).split('.')
|
||||||
|
|
||||||
|
def split_by_3(self, number):
|
||||||
|
"""
|
||||||
|
starting here, it groups the number by three from the tail
|
||||||
|
'1234567' -> (('1',),('234',),('567',))
|
||||||
|
:param number:str
|
||||||
|
:rtype:tuple
|
||||||
|
"""
|
||||||
|
blocks = ()
|
||||||
|
length = len(number)
|
||||||
|
|
||||||
|
if length < 3:
|
||||||
|
blocks += ((number,),)
|
||||||
|
else:
|
||||||
|
len_of_first_block = length % 3
|
||||||
|
|
||||||
|
if len_of_first_block > 0:
|
||||||
|
first_block = number[0:len_of_first_block],
|
||||||
|
blocks += first_block,
|
||||||
|
|
||||||
|
for i in range(len_of_first_block, length, 3):
|
||||||
|
next_block = (number[i:i+3],),
|
||||||
|
blocks += next_block
|
||||||
|
|
||||||
|
return blocks
|
||||||
|
|
||||||
|
def spell(self, blocks):
|
||||||
|
"""
|
||||||
|
it adds the list of spelling to the blocks
|
||||||
|
(('1',),('034',)) -> (('1',['satu']),('234',['tiga', 'puluh', 'empat']))
|
||||||
|
:param blocks: tuple
|
||||||
|
:rtype: tuple
|
||||||
|
"""
|
||||||
|
word_blocks = ()
|
||||||
|
first_block = blocks[0]
|
||||||
|
if len(first_block[0]) == 1:
|
||||||
|
if first_block[0] == '0':
|
||||||
|
spelling = ['nol']
|
||||||
|
else:
|
||||||
|
spelling = self.BASE[int(first_block[0])]
|
||||||
|
elif len(first_block[0]) == 2:
|
||||||
|
spelling = self.puluh(first_block[0])
|
||||||
|
else:
|
||||||
|
spelling = self.ratus(first_block[0][0]) + self.puluh(first_block[0][1:3])
|
||||||
|
|
||||||
|
word_blocks += (first_block[0], spelling),
|
||||||
|
|
||||||
|
for block in blocks[1:]:
|
||||||
|
spelling = self.ratus(block[0][0]) + self.puluh(block[0][1:3])
|
||||||
|
block += spelling,
|
||||||
|
word_blocks += block,
|
||||||
|
|
||||||
|
return word_blocks
|
||||||
|
|
||||||
|
def ratus(self, number):
|
||||||
|
# it is used to spell
|
||||||
|
if number == '1':
|
||||||
|
return ['seratus']
|
||||||
|
elif number == '0':
|
||||||
|
return []
|
||||||
|
else:
|
||||||
|
return self.BASE[int(number)]+['ratus']
|
||||||
|
|
||||||
|
def puluh(self, number):
|
||||||
|
# it is used to spell
|
||||||
|
if number[0] == '1':
|
||||||
|
if number[1]== '0':
|
||||||
|
return ['sepuluh']
|
||||||
|
elif number[1] == '1':
|
||||||
|
return ['sebelas']
|
||||||
|
else:
|
||||||
|
return self.BASE[int(number[1])]+['belas']
|
||||||
|
elif number[0] == '0':
|
||||||
|
return self.BASE[int(number[1])]
|
||||||
|
else:
|
||||||
|
return self.BASE[int(number[0])]+['puluh']+ self.BASE[int(number[1])]
|
||||||
|
|
||||||
|
def spell_float(self, float_part):
|
||||||
|
# spell the float number
|
||||||
|
word_list = []
|
||||||
|
for n in float_part:
|
||||||
|
if n == '0':
|
||||||
|
word_list += ['nol']
|
||||||
|
continue
|
||||||
|
word_list += self.BASE[int(n)]
|
||||||
|
return ' '.join(['','koma']+word_list)
|
||||||
|
|
||||||
|
def join(self, word_blocks, float_part):
|
||||||
|
"""
|
||||||
|
join the words by first join lists in the tuple
|
||||||
|
:param word_blocks: tuple
|
||||||
|
:rtype: str
|
||||||
|
"""
|
||||||
|
word_list = []
|
||||||
|
length = len(word_blocks)-1
|
||||||
|
first_block = word_blocks[0],
|
||||||
|
start = 0
|
||||||
|
|
||||||
|
if length == 1 and first_block[0][0] == '1':
|
||||||
|
word_list += ['seribu']
|
||||||
|
start = 1
|
||||||
|
|
||||||
|
for i in range(start, length+1, 1):
|
||||||
|
word_list += word_blocks[i][1]
|
||||||
|
if not word_blocks[i][1]:
|
||||||
|
continue
|
||||||
|
if i == length:
|
||||||
|
break
|
||||||
|
word_list += [self.TENS_TO[(length-i)*3]]
|
||||||
|
|
||||||
|
return ' '.join(word_list)+float_part
|
||||||
|
|
||||||
|
def to_cardinal(self, number):
|
||||||
|
if number >= self.max_num:
|
||||||
|
raise OverflowError(self.errmsg_toobig % (number, self.maxnum))
|
||||||
|
minus = ''
|
||||||
|
if number < 0:
|
||||||
|
minus = 'min '
|
||||||
|
float_word = ''
|
||||||
|
n = self.split_by_koma(abs(number))
|
||||||
|
if len(n)==2:
|
||||||
|
float_word = self.spell_float(n[1])
|
||||||
|
return minus + self.join(self.spell(self.split_by_3(n[0])), float_word)
|
||||||
|
|
||||||
|
def to_ordinal(self, number):
|
||||||
|
self.verify_ordinal(number)
|
||||||
|
out_word = self.to_cardinal(number)
|
||||||
|
if out_word == "satu":
|
||||||
|
return "pertama"
|
||||||
|
return "ke" + out_word
|
||||||
|
|
||||||
|
def to_ordinal_num(self, number):
|
||||||
|
self.verify_ordinal(number)
|
||||||
|
return "ke-" + str(number)
|
||||||
|
|
||||||
|
def to_currency(self, value):
|
||||||
|
return self.to_cardinal(value)+" rupiah"
|
||||||
|
|
||||||
|
def to_year(self, value):
|
||||||
|
return self.to_cardinal(value)
|
||||||
|
|
||||||
|
def verify_ordinal(self, value):
|
||||||
|
if not value == long(value):
|
||||||
|
raise TypeError, self.errmsg_floatord %(value)
|
||||||
|
if not abs(value) == value:
|
||||||
|
raise TypeError, self.errmsg_negord %(value)
|
||||||
49
tests/test_id.py
Normal file
49
tests/test_id.py
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
|
||||||
|
|
||||||
|
# This library is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU Lesser General Public
|
||||||
|
# License as published by the Free Software Foundation; either
|
||||||
|
# version 2.1 of the License, or (at your option) any later version.
|
||||||
|
# This library is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
# Lesser General Public License for more details.
|
||||||
|
# You should have received a copy of the GNU Lesser General Public
|
||||||
|
# License along with this library; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
# MA 02110-1301 USA
|
||||||
|
|
||||||
|
from unittest import TestCase
|
||||||
|
|
||||||
|
from num2words import num2words
|
||||||
|
|
||||||
|
class Num2WordsIDTest(TestCase):
|
||||||
|
def test_cardinal_for_natural_number(self):
|
||||||
|
self.assertEqual(num2words(10, lang='id'), "sepuluh")
|
||||||
|
self.assertEqual(num2words(11, lang='id'), "sebelas")
|
||||||
|
self.assertEqual(num2words(108, lang='id'), "seratus delapan")
|
||||||
|
self.assertEqual(num2words(1075, lang='id'), "seribu tujuh puluh lima")
|
||||||
|
self.assertEqual(num2words(1087231, lang='id'), "satu juta delapan puluh tujuh ribu dua ratus tiga puluh satu")
|
||||||
|
self.assertEqual(num2words(1000000408, lang='id'), "satu miliar empat ratus delapan")
|
||||||
|
|
||||||
|
def test_cardinal_for_decimal_number(self):
|
||||||
|
self.assertEqual(num2words(12.234, lang='id'), "dua belas koma dua tiga empat")
|
||||||
|
self.assertEqual(num2words(9.076, lang='id'), "sembilan koma nol tujuh enam")
|
||||||
|
|
||||||
|
def test_cardinal_for_negative_number(self):
|
||||||
|
self.assertEqual(num2words(-923, lang='id'), "min sembilan ratus dua puluh tiga")
|
||||||
|
self.assertEqual(num2words(-0.234, lang='id'), "min nol koma dua tiga empat")
|
||||||
|
|
||||||
|
def test_ordinal_for_natural_number(self):
|
||||||
|
self.assertEqual(num2words(1, ordinal=True, lang='id'), "pertama")
|
||||||
|
self.assertEqual(num2words(10, ordinal=True, lang='id'), "kesepuluh")
|
||||||
|
|
||||||
|
#def test_ordinal_numeric_for_natural_number(self):
|
||||||
|
# self.assertEqual(num2words(1, ordinal=True, lang='id'), "ke-1")
|
||||||
|
# self.assertEqual(num2words(10, ordinal=True, lang='id'), "ke-10")
|
||||||
|
|
||||||
|
def test_ordinal_for_negative_number(self):
|
||||||
|
self.assertRaises(TypeError, num2words, -12, ordinal=True, lang='id')
|
||||||
|
|
||||||
|
def test_ordinal_for_floating_number(self):
|
||||||
|
self.assertRaises(TypeError, num2words, 3.243, ordinal=True, lang='id')
|
||||||
Reference in New Issue
Block a user