mirror of
https://github.com/bblaz/num2words.git
synced 2025-12-06 06:42: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_PL
|
||||
from . import lang_RU
|
||||
from . import lang_ID
|
||||
|
||||
CONVERTER_CLASSES = {
|
||||
'en': lang_EN.Num2Word_EN(),
|
||||
@@ -36,6 +37,7 @@ CONVERTER_CLASSES = {
|
||||
'fr_CH': lang_FR_CH.Num2Word_FR_CH(),
|
||||
'de': lang_DE.Num2Word_DE(),
|
||||
'es': lang_ES.Num2Word_ES(),
|
||||
'id': lang_ID.Num2Word_ID(),
|
||||
'lt': lang_LT.Num2Word_LT(),
|
||||
'lv': lang_LV.Num2Word_LV(),
|
||||
'pl': lang_PL.Num2Word_PL(),
|
||||
|
||||
@@ -182,7 +182,7 @@ class Num2Word_Base(object):
|
||||
pass
|
||||
|
||||
|
||||
def to_ordinal(value):
|
||||
def to_ordinal(self, 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