Launchpad automatic translations update.
[odoo/odoo.git] / bin / tools / amount_to_text.py
1 # -*- coding: utf-8 -*-
2 ##############################################################################
3 #    
4 #    OpenERP, Open Source Management Solution
5 #    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
6 #
7 #    This program is free software: you can redistribute it and/or modify
8 #    it under the terms of the GNU Affero General Public License as
9 #    published by the Free Software Foundation, either version 3 of the
10 #    License, or (at your option) any later version.
11 #
12 #    This program is distributed in the hope that it will be useful,
13 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
14 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 #    GNU Affero General Public License for more details.
16 #
17 #    You should have received a copy of the GNU Affero General Public License
18 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.     
19 #
20 ##############################################################################
21
22 #-------------------------------------------------------------
23 # French
24 #-------------------------------------------------------------
25
26
27 to_19_fr = ( 'zéro',  'un',   'deux',  'trois', 'quatre',   'cinq',   'six',
28           'sept', 'huit', 'neuf', 'dix',   'onze', 'douze', 'treize',
29           'quatorze', 'quinze', 'seize', 'dix-sept', 'dix-huit', 'dix-neuf' )
30 tens_fr  = ( 'vingt', 'trente', 'quarante', 'Cinquante', 'Soixante', 'Soixante-dix', 'Quatre-vingts', 'Quatre-vingt Dix')
31 denom_fr = ( '',
32           'Mille',     'Millions',         'Milliards',       'Billions',       'Quadrillions',
33           'Quintillion',  'Sextillion',      'Septillion',    'Octillion',      'Nonillion',
34           'Décillion',    'Undecillion',     'Duodecillion',  'Tredecillion',   'Quattuordecillion',
35           'Sexdecillion', 'Septendecillion', 'Octodecillion', 'Icosillion', 'Vigintillion' )
36
37 # convert a value < 100 to French.
38 def _convert_nn_fr(val):
39     if val < 20:
40         return to_19_fr[val]
41     for (dcap, dval) in ((k, 20 + (10 * v)) for (v, k) in enumerate(tens_fr)):
42         if dval + 10 > val:
43             if val % 10:
44                 return dcap + '-' + to_19_fr[val % 10]
45             return dcap
46
47 # convert a value < 1000 to french, special cased because it is the level that kicks 
48 # off the < 100 special case.  The rest are more general.  This also allows you to
49 # get strings in the form of 'forty-five hundred' if called directly.
50 def _convert_nnn_fr(val):
51     word = ''
52     (mod, rem) = (val % 100, val // 100)
53     if rem > 0:
54         word = to_19_fr[rem] + ' Cent'
55         if mod > 0:
56             word = word + ' '
57     if mod > 0:
58         word = word + _convert_nn_fr(mod)
59     return word
60
61 def french_number(val):
62     if val < 100:
63         return _convert_nn_fr(val)
64     if val < 1000:
65          return _convert_nnn_fr(val)
66     for (didx, dval) in ((v - 1, 1000 ** v) for v in range(len(denom_fr))):
67         if dval > val:
68             mod = 1000 ** didx
69             l = val // mod
70             r = val - (l * mod)
71             ret = _convert_nnn_fr(l) + ' ' + denom_fr[didx]
72             if r > 0:
73                 ret = ret + ', ' + french_number(r)
74             return ret
75
76 def amount_to_text_fr(number, currency):
77     number = '%.2f' % number
78     units_name = currency
79     list = str(number).split('.')
80     start_word = french_number(abs(int(list[0])))
81     end_word = french_number(int(list[1]))
82     cents_number = int(list[1])
83     cents_name = (cents_number > 1) and ' Cents' or ' Cent'
84     final_result = start_word +' '+units_name+' '+ end_word +' '+cents_name
85     return final_result
86
87 #-------------------------------------------------------------
88 # Dutch
89 #-------------------------------------------------------------
90
91 to_19_nl = ( 'Nul',  'Een',   'Twee',  'Drie', 'Vier',   'Vijf',   'Zes',
92           'Zeven', 'Acht', 'Negen', 'Tien',   'Elf', 'Twaalf', 'Dertien',
93           'Veertien', 'Vijftien', 'Zestien', 'Zeventien', 'Achttien', 'Negentien' )
94 tens_nl  = ( 'Twintig', 'Dertig', 'Veertig', 'Vijftig', 'Zestig', 'Zeventig', 'Tachtig', 'Negentig')
95 denom_nl = ( '',
96           'Duizend', 'Miljoen', 'Miljard', 'Triljoen', 'Quadriljoen',
97            'Quintillion', 'Sextiljoen', 'Septillion', 'Octillion', 'Nonillion',
98            'Decillion', 'Undecillion', 'Duodecillion', 'Tredecillion', 'Quattuordecillion',
99            'Sexdecillion', 'Septendecillion', 'Octodecillion', 'Novemdecillion', 'Vigintillion' )
100
101 # convert a value < 100 to Dutch.
102 def _convert_nn_nl(val):
103     if val < 20:
104         return to_19_nl[val]
105     for (dcap, dval) in ((k, 20 + (10 * v)) for (v, k) in enumerate(tens_nl)):
106         if dval + 10 > val:
107             if val % 10:
108                 return dcap + '-' + to_19_nl[val % 10]
109             return dcap
110
111 # convert a value < 1000 to Dutch, special cased because it is the level that kicks 
112 # off the < 100 special case.  The rest are more general.  This also allows you to
113 # get strings in the form of 'forty-five hundred' if called directly.
114 def _convert_nnn_nl(val):
115     word = ''
116     (mod, rem) = (val % 100, val // 100)
117     if rem > 0:
118         word = to_19_nl[rem] + ' Honderd'
119         if mod > 0:
120             word = word + ' '
121     if mod > 0:
122         word = word + _convert_nn_nl(mod)
123     return word
124
125 def dutch_number(val):
126     if val < 100:
127         return _convert_nn_nl(val)
128     if val < 1000:
129          return _convert_nnn_nl(val)
130     for (didx, dval) in ((v - 1, 1000 ** v) for v in range(len(denom_nl))):
131         if dval > val:
132             mod = 1000 ** didx
133             l = val // mod
134             r = val - (l * mod)
135             ret = _convert_nnn_nl(l) + ' ' + denom_nl[didx]
136             if r > 0:
137                 ret = ret + ', ' + dutch_number(r)
138             return ret
139
140 def amount_to_text_nl(number, currency):
141     number = '%.2f' % number
142     units_name = currency
143     list = str(number).split('.')
144     start_word = dutch_number(int(list[0]))
145     end_word = dutch_number(int(list[1]))
146     cents_number = int(list[1])
147     cents_name = (cents_number > 1) and 'cent' or 'cent'
148     final_result = start_word +' '+units_name+' '+ end_word +' '+cents_name
149     return final_result
150
151 #-------------------------------------------------------------
152 # Generic functions
153 #-------------------------------------------------------------
154
155 _translate_funcs = {'fr' : amount_to_text_fr, 'nl' : amount_to_text_nl}
156
157 def add_amount_to_text_function(lang, func):
158     _translate_funcs[lang] = func
159     
160 #TODO: we should use the country AND language (ex: septante VS soixante dix)
161 #TODO: we should use en by default, but the translation func is yet to be implemented
162 def amount_to_text(nbr, lang='fr', currency='euro'):
163     """
164     Converts an integer to its textual representation, using the language set in the context if any.
165     Example:
166         1654: mille six cent cinquante-quatre.
167     """
168 #    if nbr > 1000000:
169 ##TODO: use logger   
170 #        print "WARNING: number too large '%d', can't translate it!" % (nbr,)
171 #        return str(nbr)
172     
173     if not _translate_funcs.has_key(lang):
174 #TODO: use logger   
175         print "WARNING: no translation function found for lang: '%s'" % (lang,)
176 #TODO: (default should be en) same as above
177         lang = 'fr'
178     return _translate_funcs[lang](abs(nbr), currency)
179
180 if __name__=='__main__':
181     from sys import argv
182     
183     lang = 'nl'
184     if len(argv) < 2:
185         for i in range(1,200):
186             print i, ">>", amount_to_text(i, lang)
187         for i in range(200,999999,139):
188             print i, ">>", amount_to_text(i, lang)
189     else:
190         print amount_to_text(int(argv[1]), lang)
191
192
193 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
194