Merge pull request #93 from Sergeyzhol/master

Add Ukrainian language
This commit is contained in:
Ernesto Rodriguez Ortiz
2017-09-19 12:59:15 -04:00
committed by GitHub
4 changed files with 349 additions and 1 deletions

View File

@@ -70,6 +70,7 @@ cardinal one.
* ``ru`` (Russian)
* ``tr`` (Turkish)
* ``vn`` (Vietnamese)
* ``uk`` (Ukrainian)
You can supply values like ``fr_FR``, the code will be correctly interpreted. If
you supply an unsupported language, ``NotImplementedError`` is raised.

View File

@@ -39,6 +39,7 @@ from . import lang_ES_VE
from . import lang_ES_CO
from . import lang_VN
from . import lang_TR
from . import lang_UK
CONVERTER_CLASSES = {
@@ -64,7 +65,8 @@ CONVERTER_CLASSES = {
'he': lang_HE.Num2Word_HE(),
'it': lang_IT.Num2Word_IT(),
'vi_VN': lang_VN.Num2Word_VN(),
'tr': lang_TR.Num2Word_TR()
'tr': lang_TR.Num2Word_TR(),
'uk': lang_UK.Num2Word_UK()
}
def num2words(number, ordinal=False, lang='en'):

316
num2words/lang_UK.py Normal file
View File

@@ -0,0 +1,316 @@
# -*- encoding: 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
u"""
>>> from textwrap import fill
>>> ' '.join([str(i) for i in splitby3('1')])
u'1'
>>> ' '.join([str(i) for i in splitby3('1123')])
u'1 123'
>>> ' '.join([str(i) for i in splitby3('1234567890')])
u'1 234 567 890'
>>> print(' '.join([n2w(i) for i in range(10)]))
нуль один два три чотири п'ять шiсть сiмь вiсiм дев'ять
>>> print(fill(' '.join([n2w(i+10) for i in range(10)])))
десять одинадцять дванадцять тринадцять чотирнадцять п'ятнадцять
шiстнадцять сiмнадцять вiсiмнадцять дев'ятнадцять
>>> print(fill(' '.join([n2w(i*10) for i in range(10)])))
нуль десять двадцять тридцять сорок п'ятдесят шiстдесят сiмдесят
вiсiмдесят дев'яносто
>>> print(n2w(100))
сто
>>> print(n2w(101))
сто один
>>> print(n2w(110))
сто десять
>>> print(n2w(115))
сто п'ятнадцять
>>> print(n2w(123))
сто двадцять три
>>> print(n2w(1000))
тисяча
>>> print(n2w(1001))
тисяча один
>>> print(n2w(2012))
двi тисячi дванадцять
>>> print(n2w(12519.85))
дванадцять тисяч п'ятсот дев'ятнадцять кома вiсiмдесят п'ять
>>> print(fill(n2w(1234567890)))
мiльярд двiстi тридцать чотири мiльйона п'ятсот шiстдесят сiмь тисяч
вiссот дев'яносто
>>> print(fill(n2w(215461407892039002157189883901676)))
двiстi п'ятнадцять нонiльйонiв чотириста шiстдесят один октильйон
чотириста ссептильйонiв вiссот дев'яносто два секстильйони
тридцять дев'ять квiнтильйонiв два квадрильйони сто п'ятдесят с
трильйонiв сто вiсiмдесят дев'ять мiльярдiв вiссот вiсiмдесят три
мiльйона дев'ятсот одна тисяча шiстсот сiмдесят шiсть
>>> print(fill(n2w(719094234693663034822824384220291)))
ссот дев'ятнадцять нонiльйонiв дев'яносто чотири октильйони двiстi
тридцять чотири септильйони шiстсот дев'яносто три секстильйони
шiстсот шiстдесят три квiнтильйони тридцять чотири квадрильйони
вiссот двадцять два трильйони вiссот двадцять чотири мiльярди
триста вiсiмдесят чотири мiльйона двiстi двадцять тисяч двiстi
дев'яносто один
>>> print(to_currency(1.0, 'EUR'))
один євро, нуль центiв
>>> print(to_currency(1.0, 'UAH'))
одна гривня, нуль копiйок
>>> print(to_currency(1234.56, 'EUR'))
тисяча двiстi тридцять чотири євро, п'ятдесят шiсть центiв
>>> print(to_currency(1234.56, 'UAH'))
тисяча двiстi тридцять чотири гривнi, п'ятдесят шiсть копiйок
>>> print(to_currency(10111, 'EUR', seperator=u' та'))
сто один євро та одинадцять центiв
>>> print(to_currency(10121, 'UAH', seperator=u' та'))
сто одна гривня та двадцять одна копiйка
>>> print(to_currency(10122, 'UAH', seperator=u' та'))
сто одна гривня та двадцять одна копiйка
>>> print(to_currency(10121, 'EUR', seperator=u' та'))
сто один євро та двадцять один цент
>>> print(to_currency(-1251985, cents = False))
мiнус дванадцять тисяч п'ятьсот дев'ятнадцять євро, 85 центiв
"""
from __future__ import unicode_literals
ZERO = (u'нуль',)
ONES_FEMININE = {
1: (u'одна',),
2: (u'двi',),
3: (u'три',),
4: (u'чотири',),
5: (u'п\'ять',),
6: (u'шiсть',),
7: (u'с',),
8: (u'вiс',),
9: (u'дев\'ять',),
}
ONES = {
1: (u'один',),
2: (u'два',),
3: (u'три',),
4: (u'чотири',),
5: (u'п\'ять',),
6: (u'шiсть',),
7: (u'с',),
8: (u'вiс',),
9: (u'дев\'ять',),
}
TENS = {
0: (u'десять',),
1: (u'одинадцять',),
2: (u'дванадцять',),
3: (u'тринадцять',),
4: (u'чотирнадцять',),
5: (u'п\'ятнадцять',),
6: (u'шiстнадцять',),
7: (u'сiмнадцять',),
8: (u'вiсiмнадцять',),
9: (u'дев\'ятнадцять',),
}
TWENTIES = {
2: (u'двадцять',),
3: (u'тридцять',),
4: (u'сорок',),
5: (u'п\'ятдесят',),
6: (u'шiстдесят',),
7: (u'сiмдесят',),
8: (u'вiсiмдесят',),
9: (u'дев\'яносто',),
}
HUNDREDS = {
1: (u'сто',),
2: (u'двiстi',),
3: (u'триста',),
4: (u'чотириста',),
5: (u'п\'ятсот',),
6: (u'шiстсот',),
7: (u'ссот',),
8: (u'вiссот',),
9: (u'дев\'ятсот',),
}
THOUSANDS = {
1: (u'тисяча', u'тисячi', u'тисяч'), # 10^3
2: (u'мiльйон', u'мiльйони', u'мiльйонiв'), # 10^6
3: (u'мiльярд', u'мiльярди', u'мiльярдiв'), # 10^9
4: (u'трильйон', u'трильйони', u'трильйонiв'), # 10^12
5: (u'квадрильйон', u'квадрильйони', u'квадрильйонiв'), # 10^15
6: (u'квiнтильйон', u'квiнтильйони', u'квiнтильйонiв'), # 10^18
7: (u'секстильйон', u'секстильйони', u'секстильйонiв'), # 10^21
8: (u'септильйон', u'септильйони', u'септильйонiв'), # 10^24
9: (u'октильйон', u'октильйони', u'октильйонiв'), #10^27
10: (u'нонiльйон', u'нонiльйони', u'нонiльйонiв'), # 10^30
}
CURRENCIES = {
'UAH': (
(u'гривня', u'гривнi', u'гривень'), (u'копiйка', u'копiйки', u'копiйок')
),
'EUR': (
(u'евро', u'евро', u'евро'), (u'цент', u'центи', u'центiв')
),
}
def splitby3(n):
length = len(n)
if length > 3:
start = length % 3
if start > 0:
yield int(n[:start])
for i in range(start, length, 3):
yield int(n[i:i+3])
else:
yield int(n)
def get_digits(n):
return [int(x) for x in reversed(list(('%03d' % n)[-3:]))]
def pluralize(n, forms):
#form = 0 if n==1 else 1 if (n % 10 > 1 and n % 10 < 5 and (n % 100 < 10 or n % 100 > 20)) else 2
if (n % 100 < 10 or n % 100 > 20):
if n % 10 == 1:
form = 0
elif (n % 10 > 1 and n % 10 < 5):
form = 1
else:
form = 2
else:
form = 2
return forms[form]
def int2word(n, feminine=True):
if n < 0:
return ' '.join([u'мiнус', int2word(abs(n))])
if n == 0:
return ZERO[0]
words = []
chunks = list(splitby3(str(n)))
i = len(chunks)
for x in chunks:
i -= 1
n1, n2, n3 = get_digits(x)
if n3 > 0:
words.append(HUNDREDS[n3][0])
if n2 > 1:
words.append(TWENTIES[n2][0])
if n2 == 1:
words.append(TENS[n1][0])
#elif n1 > 0 and not (i > 0 and x == 1):
elif n1 > 0:
ones = ONES_FEMININE if i == 1 or feminine and i == 0 else ONES
words.append(ones[n1][0])
if i > 0 and ((n1+n2+n3) > 0):
words.append(pluralize(x, THOUSANDS[i]))
return ' '.join(words)
def n2w(n):
n = str(n).replace(',', '.')
if '.' in n:
left, right = n.split('.')
return u'%s кома %s' % (int2word(int(left)), int2word(int(right)))
else:
return int2word(int(n))
def to_currency(n, currency='EUR', cents=True, seperator=','):
if type(n) == int:
if n < 0:
minus = True
else:
minus = False
n = abs(n)
left = n / 100
right = n % 100
else:
n = str(n).replace(',', '.')
if '.' in n:
left, right = n.split('.')
else:
left, right = n, 0
left, right = int(left), int(right)
minus = False
cr1, cr2 = CURRENCIES[currency]
if minus:
minus_str = "мiнус "
else:
minus_str = ""
if cents:
cents_feminine = currency == 'UAH'
cents_str = int2word(right, cents_feminine)
else:
cents_str = "%02d" % right
return u'%s%s %s%s %s %s' % (
minus_str,
int2word(left),
pluralize(left, cr1),
seperator,
cents_str,
pluralize(right, cr2)
)
class Num2Word_UK(object):
def to_cardinal(self, number):
return n2w(number)
def to_ordinal(self, number):
raise NotImplementedError()
if __name__ == '__main__':
import doctest
doctest.testmod()

29
tests/test_uk.py Normal file
View File

@@ -0,0 +1,29 @@
# -*- encoding: utf-8 -*-
# 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 Num2WordsUKTest(TestCase):
def test_and_join_199(self):
self.assertEqual(num2words(187,lang='uk'), u"сто вiсiмдесят с")
def test_cardinal_for_float_number(self):
self.assertEqual(num2words(12.40,lang='uk'), u"дванадцять кома чотири")
self.assertEqual(num2words(17.31,lang='uk'), u"сiмнадцять кома тридцять одна")
self.assertEqual(num2words(14.13,lang='uk'), u"чотирнадцять кома тринадцять")
self.assertEqual(num2words(12.31,lang='uk'), u"дванадцять кома тридцять одна")