Merge branch 'filwaitman-language_pt_BR'

This commit is contained in:
Ernesto Rodriguez Ortiz
2016-03-31 14:26:58 -04:00
5 changed files with 435 additions and 4 deletions

View File

@@ -53,6 +53,7 @@ Besides the numerical argument, there's two optional arguments.
* ``pl`` (Polish)
* ``ru`` (Russian)
* ``dk`` (Danish)
* ``pt_BR`` (Brazilian Portuguese)
You can supply values like ``fr_FR``, the code will be
correctly interpreted. If you supply an unsupported language, ``NotImplementedError`` is raised.

View File

@@ -30,6 +30,7 @@ from . import lang_RU
from . import lang_ID
from . import lang_NO
from . import lang_DK
from . import lang_PT_BR
CONVERTER_CLASSES = {
'en': lang_EN.Num2Word_EN(),
@@ -46,6 +47,7 @@ CONVERTER_CLASSES = {
'ru': lang_RU.Num2Word_RU(),
'no': lang_NO.Num2Word_NO(),
'dk': lang_DK.Num2Word_DK(),
'pt_BR': lang_PT_BR.Num2Word_PT_BR(),
}
def num2words(number, ordinal=False, lang='en'):

View File

@@ -36,7 +36,7 @@ class Num2Word_Base(object):
self.set_numwords()
self.MAXVAL = 1000 * self.cards.order[0]
def set_numwords(self):
self.set_high_numwords(self.high_numwords)
@@ -64,7 +64,7 @@ class Num2Word_Base(object):
for elem in self.cards:
if elem > value:
continue
out = []
if value == 0:
div, mod = 1, 0
@@ -75,7 +75,7 @@ class Num2Word_Base(object):
out.append((self.cards[1], 1))
else:
if div == value: # The system tallies, eg Roman Numerals
return [(div * self.cards[elem], div*elem)]
return [(div * self.cards[elem], div*elem)]
out.append(self.splitnum(div))
out.append((self.cards[elem], elem))
@@ -259,6 +259,6 @@ class Num2Word_Base(object):
_ordnum = self.to_ordinal_num(value)
except:
_ordnum = "invalid"
print ("For %s, card is %s;\n\tord is %s; and\n\tordnum is %s." %
(value, _card, _ord, _ordnum))

209
num2words/lang_PT_BR.py Normal file
View File

@@ -0,0 +1,209 @@
# -*- coding: utf-8 -*-
# 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
from __future__ import division, unicode_literals
import re
from . import lang_EU
class Num2Word_PT_BR(lang_EU.Num2Word_EU):
def set_high_numwords(self, high):
max = 3 + 3*len(high)
for word, n in zip(high, range(max, 3, -3)):
self.cards[10**n] = word + "ilhão"
def setup(self):
self.negword = "menos "
self.pointword = "ponto"
self.errmsg_nornum = "Somente números podem ser convertidos para palavras"
self.exclude_title = ["e", "ponto", "menos"]
self.mid_numwords = [
(1000, "mil"), (100, "cem"), (90, "noventa"),
(80, "oitenta"), (70, "setenta"), (60, "sessenta"), (50, "cinquenta"),
(40, "quarenta"), (30, "trinta")
]
self.low_numwords = [
"vinte", "dezenove", "dezoito", "dezessete", "dezesseis",
"quinze", "catorze", "treze", "doze", "onze", "dez",
"nove", "oito", "sete", "seis", "cinco", "quatro", "três", "dois",
"um", "zero"
]
self.ords = [
{
0: "",
1: "primeiro",
2: "segundo",
3: "terceiro",
4: "quarto",
5: "quinto",
6: "sexto",
7: "sétimo",
8: "oitavo",
9: "nono",
},
{
0: "",
1: "décimo",
2: "vigésimo",
3: "trigésimo",
4: "quadragésimo",
5: "quinquagésimo",
6: "sexagésimo",
7: "septuagésimo",
8: "octogésimo",
9: "nonagésimo",
},
{
0: "",
1: "centésimo",
2: "ducentésimo",
3: "tricentésimo",
4: "quadrigentésimo",
5: "quingentésimo",
6: "seiscentésimo",
7: "septigentésimo",
8: "octigentésimo",
9: "nongentésimo",
},
]
self.thousand_separators = {
3: "milésimo",
6: "milionésimo",
9: "bilionésimo",
12: "trilionésimo",
15: "quadrilionésimo"
}
self.hundreds = {
1: "cento",
2: "duzentos",
3: "trezentos",
4: "quatrocentos",
5: "quinhentos",
6: "seiscentos",
7: "setecentos",
8: "oitocentos",
9: "novecentos",
}
def merge(self, curr, next):
ctext, cnum, ntext, nnum = curr + next
if cnum == 1:
if nnum < 1000000:
return next
ctext = "um"
elif cnum == 100 and not nnum == 1000:
ctext = "cento"
if nnum < cnum:
if cnum < 100:
return ("%s e %s" % (ctext, ntext), cnum + nnum)
return ("%s e %s" % (ctext, ntext), cnum + nnum)
elif (not nnum % 1000000) and cnum > 1:
ntext = ntext[:-4] + "lhões"
if nnum == 100:
ctext = self.hundreds[cnum]
ntext = ""
else:
ntext = " " + ntext
return (ctext + ntext, cnum * nnum)
def to_cardinal(self, value):
result = super(Num2Word_PT_BR, self).to_cardinal(value)
# Transforms "mil E cento e catorze reais" into "mil, cento e catorze reais"
for ext in (
'mil', 'milhão', 'milhões', 'bilhão', 'bilhões',
'trilhão', 'trilhões', 'quatrilhão', 'quatrilhões'):
if re.match('.*{} e \w*ento'.format(ext), result):
result = result.replace('{} e'.format(ext), '{},'.format(ext), 1)
return result
def to_ordinal(self, value):
self.verify_ordinal(value)
result = []
value = str(value)
thousand_separator = ''
for idx, char in enumerate(value[::-1]):
if idx and idx % 3 == 0:
thousand_separator = self.thousand_separators[idx]
if char != '0' and thousand_separator:
# avoiding "segundo milionésimo milésimo" for 6000000, for instance
result.append(thousand_separator)
thousand_separator = ''
result.append(self.ords[idx % 3][int(char)])
result = ' '.join(result[::-1])
result = result.strip()
result = re.sub('\s+', ' ', result)
if result.startswith('primeiro') and value != '1':
# avoiding "primeiro milésimo", "primeiro milionésimo" and so on
result = result[9:]
return result
def to_ordinal_num(self, value):
self.verify_ordinal(value)
return "%sº" % (value)
def to_year(self, val, longval=True):
if val < 0:
return self.to_cardinal(abs(val)) + ' antes de Cristo'
return self.to_cardinal(val)
def to_currency(self, val, longval=True):
integer_part, decimal_part = ('%.2f' % val).split('.')
result = self.to_cardinal(int(integer_part))
appended_currency = False
for ext in (
'milhão', 'milhões', 'bilhão', 'bilhões',
'trilhão', 'trilhões', 'quatrilhão', 'quatrilhões'):
if result.endswith(ext):
result += ' de reais'
appended_currency = True
if result in ['um', 'menos um']:
result += ' real'
appended_currency = True
if not appended_currency:
result += ' reais'
if int(decimal_part):
cents = self.to_cardinal(int(decimal_part))
result += ' e ' + cents
if cents == 'um':
result += ' centavo'
else:
result += ' centavos'
return result

219
tests/test_pt_BR.py Normal file
View File

@@ -0,0 +1,219 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2015, 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 __future__ import unicode_literals
from decimal import Decimal
from unittest import TestCase
from num2words import num2words
from num2words.lang_PT_BR import Num2Word_PT_BR
class Num2WordsPTBRTest(TestCase):
def setUp(self):
super(Num2WordsPTBRTest, self).setUp()
self.n2w = Num2Word_PT_BR()
def test_cardinal_integer(self):
self.assertEquals(num2words(1, lang='pt_BR'), 'um')
self.assertEquals(num2words(2, lang='pt_BR'), 'dois')
self.assertEquals(num2words(3, lang='pt_BR'), 'três')
self.assertEquals(num2words(4, lang='pt_BR'), 'quatro')
self.assertEquals(num2words(5, lang='pt_BR'), 'cinco')
self.assertEquals(num2words(6, lang='pt_BR'), 'seis')
self.assertEquals(num2words(7, lang='pt_BR'), 'sete')
self.assertEquals(num2words(8, lang='pt_BR'), 'oito')
self.assertEquals(num2words(9, lang='pt_BR'), 'nove')
self.assertEquals(num2words(10, lang='pt_BR'), 'dez')
self.assertEquals(num2words(11, lang='pt_BR'), 'onze')
self.assertEquals(num2words(12, lang='pt_BR'), 'doze')
self.assertEquals(num2words(13, lang='pt_BR'), 'treze')
self.assertEquals(num2words(14, lang='pt_BR'), 'catorze')
self.assertEquals(num2words(15, lang='pt_BR'), 'quinze')
self.assertEquals(num2words(16, lang='pt_BR'), 'dezesseis')
self.assertEquals(num2words(17, lang='pt_BR'), 'dezessete')
self.assertEquals(num2words(18, lang='pt_BR'), 'dezoito')
self.assertEquals(num2words(19, lang='pt_BR'), 'dezenove')
self.assertEquals(num2words(20, lang='pt_BR'), 'vinte')
self.assertEquals(num2words(21, lang='pt_BR'), 'vinte e um')
self.assertEquals(num2words(22, lang='pt_BR'), 'vinte e dois')
self.assertEquals(num2words(35, lang='pt_BR'), 'trinta e cinco')
self.assertEquals(num2words(99, lang='pt_BR'), 'noventa e nove')
self.assertEquals(num2words(100, lang='pt_BR'), 'cem')
self.assertEquals(num2words(101, lang='pt_BR'), 'cento e um')
self.assertEquals(num2words(128, lang='pt_BR'), 'cento e vinte e oito')
self.assertEquals(num2words(713, lang='pt_BR'), 'setecentos e treze')
self.assertEquals(num2words(1000, lang='pt_BR'), 'mil')
self.assertEquals(num2words(1001, lang='pt_BR'), 'mil e um')
self.assertEquals(num2words(1111, lang='pt_BR'), 'mil, cento e onze')
self.assertEquals(num2words(2114, lang='pt_BR'), 'dois mil, cento e catorze')
self.assertEquals(num2words(73421, lang='pt_BR'), 'setenta e três mil, quatrocentos e vinte e um')
self.assertEquals(num2words(100000, lang='pt_BR'), 'cem mil')
self.assertEquals(num2words(250050, lang='pt_BR'), 'duzentos e cinquenta mil e cinquenta')
self.assertEquals(num2words(6000000, lang='pt_BR'), 'seis milhões')
self.assertEquals(num2words(19000000000, lang='pt_BR'), 'dezenove bilhões')
self.assertEquals(num2words(145000000002, lang='pt_BR'), 'cento e quarenta e cinco bilhões e dois')
def test_cardinal_integer_negative(self):
self.assertEquals(num2words(-1, lang='pt_BR'), 'menos um')
self.assertEquals(num2words(-256, lang='pt_BR'), 'menos duzentos e cinquenta e seis')
self.assertEquals(num2words(-1000, lang='pt_BR'), 'menos mil')
self.assertEquals(num2words(-1000000, lang='pt_BR'), 'menos um milhão')
self.assertEquals(num2words(-1234567, lang='pt_BR'), 'menos um milhão, duzentos e trinta e quatro mil, quinhentos e sessenta e sete')
def test_cardinal_float(self):
self.assertEquals(num2words(Decimal('1.00'), lang='pt_BR'), 'um')
self.assertEquals(num2words(Decimal('1.01'), lang='pt_BR'), 'um ponto zero um')
self.assertEquals(num2words(Decimal('1.035'), lang='pt_BR'), 'um ponto zero três')
self.assertEquals(num2words(Decimal('1.35'), lang='pt_BR'), 'um ponto três cinco')
self.assertEquals(num2words(Decimal('3.14159'), lang='pt_BR'), 'três ponto um quatro')
self.assertEquals(num2words(Decimal('101.22'), lang='pt_BR'), 'cento e um ponto dois dois')
self.assertEquals(num2words(Decimal('2345.75'), lang='pt_BR'), 'dois mil, trezentos e quarenta e cinco ponto sete cinco')
def test_cardinal_float_negative(self):
self.assertEquals(num2words(Decimal('-2.34'), lang='pt_BR'), 'menos dois ponto três quatro')
self.assertEquals(num2words(Decimal('-9.99'), lang='pt_BR'), 'menos nove ponto nove nove')
self.assertEquals(num2words(Decimal('-7.01'), lang='pt_BR'), 'menos sete ponto zero um')
self.assertEquals(num2words(Decimal('-222.22'), lang='pt_BR'), 'menos duzentos e vinte e dois ponto dois dois')
def test_ordinal(self):
self.assertEquals(num2words(1, lang='pt_BR', ordinal=True), 'primeiro')
self.assertEquals(num2words(2, lang='pt_BR', ordinal=True), 'segundo')
self.assertEquals(num2words(3, lang='pt_BR', ordinal=True), 'terceiro')
self.assertEquals(num2words(4, lang='pt_BR', ordinal=True), 'quarto')
self.assertEquals(num2words(5, lang='pt_BR', ordinal=True), 'quinto')
self.assertEquals(num2words(6, lang='pt_BR', ordinal=True), 'sexto')
self.assertEquals(num2words(7, lang='pt_BR', ordinal=True), 'sétimo')
self.assertEquals(num2words(8, lang='pt_BR', ordinal=True), 'oitavo')
self.assertEquals(num2words(9, lang='pt_BR', ordinal=True), 'nono')
self.assertEquals(num2words(10, lang='pt_BR', ordinal=True), 'décimo')
self.assertEquals(num2words(11, lang='pt_BR', ordinal=True), 'décimo primeiro')
self.assertEquals(num2words(12, lang='pt_BR', ordinal=True), 'décimo segundo')
self.assertEquals(num2words(13, lang='pt_BR', ordinal=True), 'décimo terceiro')
self.assertEquals(num2words(14, lang='pt_BR', ordinal=True), 'décimo quarto')
self.assertEquals(num2words(15, lang='pt_BR', ordinal=True), 'décimo quinto')
self.assertEquals(num2words(16, lang='pt_BR', ordinal=True), 'décimo sexto')
self.assertEquals(num2words(17, lang='pt_BR', ordinal=True), 'décimo sétimo')
self.assertEquals(num2words(18, lang='pt_BR', ordinal=True), 'décimo oitavo')
self.assertEquals(num2words(19, lang='pt_BR', ordinal=True), 'décimo nono')
self.assertEquals(num2words(20, lang='pt_BR', ordinal=True), 'vigésimo')
self.assertEquals(num2words(21, lang='pt_BR', ordinal=True), 'vigésimo primeiro')
self.assertEquals(num2words(22, lang='pt_BR', ordinal=True), 'vigésimo segundo')
self.assertEquals(num2words(35, lang='pt_BR', ordinal=True), 'trigésimo quinto')
self.assertEquals(num2words(99, lang='pt_BR', ordinal=True), 'nonagésimo nono')
self.assertEquals(num2words(100, lang='pt_BR', ordinal=True), 'centésimo')
self.assertEquals(num2words(101, lang='pt_BR', ordinal=True), 'centésimo primeiro')
self.assertEquals(num2words(128, lang='pt_BR', ordinal=True), 'centésimo vigésimo oitavo')
self.assertEquals(num2words(713, lang='pt_BR', ordinal=True), 'septigentésimo décimo terceiro')
self.assertEquals(num2words(1000, lang='pt_BR', ordinal=True), 'milésimo')
self.assertEquals(num2words(1001, lang='pt_BR', ordinal=True), 'milésimo primeiro')
self.assertEquals(num2words(1111, lang='pt_BR', ordinal=True), 'milésimo centésimo décimo primeiro')
self.assertEquals(num2words(2114, lang='pt_BR', ordinal=True), 'segundo milésimo centésimo décimo quarto')
self.assertEquals(num2words(73421, lang='pt_BR', ordinal=True), 'septuagésimo terceiro milésimo quadrigentésimo vigésimo primeiro')
self.assertEquals(num2words(100000, lang='pt_BR', ordinal=True), 'centésimo milésimo')
self.assertEquals(num2words(250050, lang='pt_BR', ordinal=True), 'ducentésimo quinquagésimo milésimo quinquagésimo')
self.assertEquals(num2words(6000000, lang='pt_BR', ordinal=True), 'sexto milionésimo')
self.assertEquals(num2words(19000000000, lang='pt_BR', ordinal=True), 'décimo nono bilionésimo')
self.assertEquals(num2words(145000000002, lang='pt_BR', ordinal=True), 'centésimo quadragésimo quinto bilionésimo segundo')
def test_currency_integer(self):
self.assertEquals(self.n2w.to_currency(1), 'um real')
self.assertEquals(self.n2w.to_currency(2), 'dois reais')
self.assertEquals(self.n2w.to_currency(3), 'três reais')
self.assertEquals(self.n2w.to_currency(4), 'quatro reais')
self.assertEquals(self.n2w.to_currency(5), 'cinco reais')
self.assertEquals(self.n2w.to_currency(6), 'seis reais')
self.assertEquals(self.n2w.to_currency(7), 'sete reais')
self.assertEquals(self.n2w.to_currency(8), 'oito reais')
self.assertEquals(self.n2w.to_currency(9), 'nove reais')
self.assertEquals(self.n2w.to_currency(10), 'dez reais')
self.assertEquals(self.n2w.to_currency(11), 'onze reais')
self.assertEquals(self.n2w.to_currency(12), 'doze reais')
self.assertEquals(self.n2w.to_currency(13), 'treze reais')
self.assertEquals(self.n2w.to_currency(14), 'catorze reais')
self.assertEquals(self.n2w.to_currency(15), 'quinze reais')
self.assertEquals(self.n2w.to_currency(16), 'dezesseis reais')
self.assertEquals(self.n2w.to_currency(17), 'dezessete reais')
self.assertEquals(self.n2w.to_currency(18), 'dezoito reais')
self.assertEquals(self.n2w.to_currency(19), 'dezenove reais')
self.assertEquals(self.n2w.to_currency(20), 'vinte reais')
self.assertEquals(self.n2w.to_currency(21), 'vinte e um reais')
self.assertEquals(self.n2w.to_currency(22), 'vinte e dois reais')
self.assertEquals(self.n2w.to_currency(35), 'trinta e cinco reais')
self.assertEquals(self.n2w.to_currency(99), 'noventa e nove reais')
self.assertEquals(self.n2w.to_currency(100), 'cem reais')
self.assertEquals(self.n2w.to_currency(101), 'cento e um reais')
self.assertEquals(self.n2w.to_currency(128), 'cento e vinte e oito reais')
self.assertEquals(self.n2w.to_currency(713), 'setecentos e treze reais')
self.assertEquals(self.n2w.to_currency(1000), 'mil reais')
self.assertEquals(self.n2w.to_currency(1001), 'mil e um reais')
self.assertEquals(self.n2w.to_currency(1111), 'mil, cento e onze reais')
self.assertEquals(self.n2w.to_currency(2114), 'dois mil, cento e catorze reais')
self.assertEquals(self.n2w.to_currency(73421), 'setenta e três mil, quatrocentos e vinte e um reais')
self.assertEquals(self.n2w.to_currency(100000), 'cem mil reais')
self.assertEquals(self.n2w.to_currency(250050), 'duzentos e cinquenta mil e cinquenta reais')
self.assertEquals(self.n2w.to_currency(6000000), 'seis milhões de reais')
self.assertEquals(self.n2w.to_currency(19000000000), 'dezenove bilhões de reais')
self.assertEquals(self.n2w.to_currency(145000000002), 'cento e quarenta e cinco bilhões e dois reais')
def test_currency_integer_negative(self):
self.assertEquals(self.n2w.to_currency(-1), 'menos um real')
self.assertEquals(self.n2w.to_currency(-256), 'menos duzentos e cinquenta e seis reais')
self.assertEquals(self.n2w.to_currency(-1000), 'menos mil reais')
self.assertEquals(self.n2w.to_currency(-1000000), 'menos um milhão de reais')
self.assertEquals(self.n2w.to_currency(-1234567), 'menos um milhão, duzentos e trinta e quatro mil, quinhentos e sessenta e sete reais')
def test_currency_float(self):
self.assertEquals(self.n2w.to_currency(Decimal('1.00')), 'um real')
self.assertEquals(self.n2w.to_currency(Decimal('1.01')), 'um real e um centavo')
self.assertEquals(self.n2w.to_currency(Decimal('1.035')), 'um real e três centavos')
self.assertEquals(self.n2w.to_currency(Decimal('1.35')), 'um real e trinta e cinco centavos')
self.assertEquals(self.n2w.to_currency(Decimal('3.14159')), 'três reais e catorze centavos')
self.assertEquals(self.n2w.to_currency(Decimal('101.22')), 'cento e um reais e vinte e dois centavos')
self.assertEquals(self.n2w.to_currency(Decimal('2345.75')), 'dois mil, trezentos e quarenta e cinco reais e setenta e cinco centavos')
def test_currency_float_negative(self):
self.assertEquals(self.n2w.to_currency(Decimal('-2.34')), 'menos dois reais e trinta e quatro centavos')
self.assertEquals(self.n2w.to_currency(Decimal('-9.99')), 'menos nove reais e noventa e nove centavos')
self.assertEquals(self.n2w.to_currency(Decimal('-7.01')), 'menos sete reais e um centavo')
self.assertEquals(self.n2w.to_currency(Decimal('-222.22')), 'menos duzentos e vinte e dois reais e vinte e dois centavos')
def test_year(self):
self.assertEquals(self.n2w.to_year(1001), 'mil e um')
self.assertEquals(self.n2w.to_year(1789), 'mil, setecentos e oitenta e nove')
self.assertEquals(self.n2w.to_year(1942), 'mil, novecentos e quarenta e dois')
self.assertEquals(self.n2w.to_year(1984), 'mil, novecentos e oitenta e quatro')
self.assertEquals(self.n2w.to_year(2000), 'dois mil')
self.assertEquals(self.n2w.to_year(2001), 'dois mil e um')
self.assertEquals(self.n2w.to_year(2016), 'dois mil e dezesseis')
def test_year_negative(self):
self.assertEquals(self.n2w.to_year(-30), 'trinta antes de Cristo')
self.assertEquals(self.n2w.to_year(-744), 'setecentos e quarenta e quatro antes de Cristo')
self.assertEquals(self.n2w.to_year(-10000), 'dez mil antes de Cristo')