0
# Base Converter Architecture
1
2
The foundation of num2words is the `Num2Word_Base` class, which provides the core architecture and methods that all language-specific converters inherit from. This design enables consistent behavior across all 50+ supported languages while allowing for language-specific customizations.
3
4
## Capabilities
5
6
### Base Converter Class
7
8
The foundation class that all language converters inherit from.
9
10
```python { .api }
11
class Num2Word_Base:
12
"""
13
Base class for all language-specific number-to-word converters.
14
15
Attributes:
16
- CURRENCY_FORMS: dict - Currency format definitions for the language
17
- CURRENCY_ADJECTIVES: dict - Currency adjective forms
18
- is_title: bool - Whether to title-case output
19
- precision: int - Decimal precision for float handling
20
- negword: str - Prefix for negative numbers
21
- pointword: str - Word for decimal point
22
- cards: OrderedDict - Number word mappings
23
- MAXVAL: int - Maximum supported number value
24
"""
25
26
def __init__(self): ...
27
```
28
29
**Usage Examples:**
30
31
```python
32
from num2words.base import Num2Word_Base
33
34
# Access base converter (not typically used directly)
35
base_converter = Num2Word_Base()
36
37
# Language converters inherit from this base
38
from num2words import CONVERTER_CLASSES
39
english_converter = CONVERTER_CLASSES['en']
40
print(type(english_converter).__bases__) # Shows Num2Word_Base in inheritance
41
```
42
43
### Cardinal Number Conversion
44
45
Core method for converting numbers to cardinal word form.
46
47
```python { .api }
48
def to_cardinal(self, value):
49
"""
50
Convert number to cardinal word representation.
51
52
Parameters:
53
- value: int/float - Number to convert
54
55
Returns:
56
str - Cardinal number as words
57
58
Raises:
59
OverflowError - If number exceeds MAXVAL
60
"""
61
```
62
63
**Usage Examples:**
64
65
```python
66
from num2words import CONVERTER_CLASSES
67
68
# Access converter directly
69
en_converter = CONVERTER_CLASSES['en']
70
result = en_converter.to_cardinal(42) # "forty-two"
71
result = en_converter.to_cardinal(-15) # "minus fifteen"
72
result = en_converter.to_cardinal(1000) # "one thousand"
73
74
# Different languages
75
fr_converter = CONVERTER_CLASSES['fr']
76
result = fr_converter.to_cardinal(42) # "quarante-deux"
77
```
78
79
### Float Number Conversion
80
81
Specialized handling for floating-point numbers.
82
83
```python { .api }
84
def to_cardinal_float(self, value):
85
"""
86
Convert floating-point number to word representation.
87
88
Handles decimal precision and fractional parts appropriately.
89
90
Parameters:
91
- value: float - Float number to convert
92
93
Returns:
94
str - Float number with decimal point as words
95
96
Raises:
97
TypeError - For invalid number types
98
"""
99
```
100
101
**Usage Examples:**
102
103
```python
104
en_converter = CONVERTER_CLASSES['en']
105
result = en_converter.to_cardinal_float(42.5) # "forty-two point five"
106
result = en_converter.to_cardinal_float(3.14) # "three point one four"
107
result = en_converter.to_cardinal_float(0.001) # "zero point zero zero one"
108
```
109
110
### Ordinal Number Conversion
111
112
Convert numbers to ordinal form (language-dependent implementation).
113
114
```python { .api }
115
def to_ordinal(self, value):
116
"""
117
Convert number to ordinal word representation.
118
119
Base implementation delegates to to_cardinal.
120
Language subclasses override for proper ordinal forms.
121
122
Parameters:
123
- value: int - Integer to convert to ordinal
124
125
Returns:
126
str - Ordinal number as words
127
128
Raises:
129
TypeError - For float inputs or negative numbers
130
"""
131
```
132
133
**Usage Examples:**
134
135
```python
136
en_converter = CONVERTER_CLASSES['en']
137
result = en_converter.to_ordinal(1) # "first"
138
result = en_converter.to_ordinal(2) # "second"
139
result = en_converter.to_ordinal(21) # "twenty-first"
140
result = en_converter.to_ordinal(42) # "forty-second"
141
142
# Validation
143
try:
144
en_converter.to_ordinal(42.5) # Floats not allowed
145
except TypeError:
146
print("Ordinals require integers")
147
```
148
149
### Ordinal Number (Numeric) Conversion
150
151
Convert numbers to numeric ordinal form.
152
153
```python { .api }
154
def to_ordinal_num(self, value):
155
"""
156
Convert number to numeric ordinal representation.
157
158
Base implementation returns the number unchanged.
159
Language subclasses override for proper suffixes.
160
161
Parameters:
162
- value: int - Integer to convert
163
164
Returns:
165
str - Numeric ordinal (e.g., "42nd")
166
"""
167
```
168
169
**Usage Examples:**
170
171
```python
172
en_converter = CONVERTER_CLASSES['en']
173
result = en_converter.to_ordinal_num(1) # "1st"
174
result = en_converter.to_ordinal_num(2) # "2nd"
175
result = en_converter.to_ordinal_num(3) # "3rd"
176
result = en_converter.to_ordinal_num(4) # "4th"
177
result = en_converter.to_ordinal_num(21) # "21st"
178
```
179
180
### Year Conversion
181
182
Convert numbers to year word format.
183
184
```python { .api }
185
def to_year(self, value, **kwargs):
186
"""
187
Convert number to year word representation.
188
189
Base implementation delegates to to_cardinal.
190
Language subclasses can override for year-specific formatting.
191
192
Parameters:
193
- value: int - Year to convert
194
- **kwargs: Language-specific year formatting options
195
196
Returns:
197
str - Year as words
198
"""
199
```
200
201
**Usage Examples:**
202
203
```python
204
en_converter = CONVERTER_CLASSES['en']
205
result = en_converter.to_year(1984) # "nineteen eighty-four"
206
result = en_converter.to_year(2000) # "two thousand"
207
result = en_converter.to_year(2023) # "twenty twenty-three"
208
```
209
210
### Currency Conversion
211
212
Convert numbers to currency format with proper localization.
213
214
```python { .api }
215
def to_currency(self, val, currency='EUR', cents=True, separator=',', adjective=False):
216
"""
217
Convert number to currency word representation.
218
219
Parameters:
220
- val: int/float - Currency value
221
- currency: str - Currency code (default: 'EUR')
222
- cents: bool - Include verbose cents (default: True)
223
- separator: str - Separator between currency and cents (default: ',')
224
- adjective: bool - Include currency adjective prefix (default: False)
225
226
Returns:
227
str - Formatted currency string
228
229
Raises:
230
NotImplementedError - If currency not supported for language
231
"""
232
```
233
234
**Usage Examples:**
235
236
```python
237
en_converter = CONVERTER_CLASSES['en']
238
result = en_converter.to_currency(42.50)
239
# "forty-two euros, fifty cents"
240
241
result = en_converter.to_currency(42.50, currency='USD')
242
# "forty-two dollars, fifty cents"
243
244
result = en_converter.to_currency(42.50, cents=False)
245
# "forty-two euros, 50"
246
247
result = en_converter.to_currency(42.50, separator=' and ')
248
# "forty-two euros and fifty cents"
249
```
250
251
### String to Number Conversion
252
253
Convert string representations to numeric values.
254
255
```python { .api }
256
def str_to_number(self, value):
257
"""
258
Convert string to Decimal number for processing.
259
260
Parameters:
261
- value: str - String representation of number
262
263
Returns:
264
Decimal - Parsed number
265
266
Raises:
267
ValueError - For invalid string formats
268
"""
269
```
270
271
**Usage Examples:**
272
273
```python
274
en_converter = CONVERTER_CLASSES['en']
275
number = en_converter.str_to_number("42") # Decimal('42')
276
number = en_converter.str_to_number("42.5") # Decimal('42.5')
277
number = en_converter.str_to_number("-15") # Decimal('-15')
278
```
279
280
### Number Splitting and Processing
281
282
Internal methods for breaking down numbers according to language rules.
283
284
```python { .api }
285
def splitnum(self, value):
286
"""
287
Split number into components according to language rules.
288
289
Parameters:
290
- value: int - Number to split
291
292
Returns:
293
list - Structured number components for word generation
294
"""
295
296
def float2tuple(self, value):
297
"""
298
Split float into integer and fractional parts.
299
300
Parameters:
301
- value: float - Float to split
302
303
Returns:
304
tuple - (integer_part, fractional_part)
305
"""
306
```
307
308
**Usage Examples:**
309
310
```python
311
en_converter = CONVERTER_CLASSES['en']
312
313
# Split complex numbers
314
components = en_converter.splitnum(1234567)
315
# Returns structured breakdown for "one million, two hundred..."
316
317
# Split floats
318
integer_part, fractional_part = en_converter.float2tuple(42.567)
319
# Returns (42, 567) with appropriate precision handling
320
```
321
322
### Language Setup and Customization
323
324
Methods for configuring language-specific behavior.
325
326
```python { .api }
327
def setup(self):
328
"""
329
Language-specific setup method.
330
331
Override in language subclasses to configure:
332
- negword: Negative number prefix
333
- pointword: Decimal point word
334
- exclude_title: Words to exclude from title casing
335
- Number word dictionaries and mappings
336
"""
337
338
def set_numwords(self):
339
"""Set up number word dictionaries from language definitions."""
340
341
def set_high_numwords(self, *args):
342
"""Set up high-value number words (millions, billions, etc.)."""
343
344
def set_mid_numwords(self, mid):
345
"""Set up mid-range number words (tens, hundreds)."""
346
347
def set_low_numwords(self, numwords):
348
"""Set up low-value number words (0-19)."""
349
```
350
351
### Advanced Number Splitting
352
353
Specialized method for splitting numbers with custom formatting options.
354
355
```python { .api }
356
def to_splitnum(self, val, hightxt="", lowtxt="", jointxt="", divisor=100, longval=True, cents=True):
357
"""
358
Split number into high and low components with custom formatting.
359
360
Primarily used for currency and complex number formatting.
361
362
Parameters:
363
- val: int/float/tuple - Value to split
364
- hightxt: str - Text for high component
365
- lowtxt: str - Text for low component
366
- jointxt: str - Text to join components
367
- divisor: int - Division factor (default: 100)
368
- longval: bool - Use verbose format (default: True)
369
- cents: bool - Verbose cents representation (default: True)
370
371
Returns:
372
str - Formatted split number string
373
"""
374
```
375
376
**Usage Examples:**
377
378
```python
379
en_converter = CONVERTER_CLASSES['en']
380
381
# Currency-style splitting
382
result = en_converter.to_splitnum(42.50, hightxt="dollars", lowtxt="cents")
383
# "forty-two dollars fifty cents"
384
385
# Custom splitting with divisor
386
result = en_converter.to_splitnum(365, hightxt="years", lowtxt="days", divisor=365)
387
# Custom format based on divisor
388
```
389
390
### Currency Internal Methods
391
392
Internal methods used by `to_currency()` for formatting currency components.
393
394
```python { .api }
395
def _money_verbose(self, number, currency):
396
"""
397
Convert currency major unit to verbose representation.
398
399
Parameters:
400
- number: int - Major currency unit
401
- currency: str - Currency code
402
403
Returns:
404
str - Verbose representation of major currency unit
405
"""
406
407
def _cents_verbose(self, number, currency):
408
"""
409
Convert currency minor unit to verbose representation.
410
411
Parameters:
412
- number: int - Minor currency unit (cents)
413
- currency: str - Currency code
414
415
Returns:
416
str - Verbose representation of minor currency unit
417
"""
418
419
def _cents_terse(self, number, currency):
420
"""
421
Convert currency minor unit to terse numeric representation.
422
423
Parameters:
424
- number: int - Minor currency unit (cents)
425
- currency: str - Currency code
426
427
Returns:
428
str - Terse numeric representation (e.g., "50")
429
"""
430
```
431
432
**Usage Examples:**
433
434
```python
435
en_converter = CONVERTER_CLASSES['en']
436
437
# These are internal methods used by to_currency()
438
money_part = en_converter._money_verbose(42, 'EUR') # "forty-two"
439
cents_part = en_converter._cents_verbose(50, 'EUR') # "fifty"
440
cents_terse = en_converter._cents_terse(50, 'EUR') # "50"
441
```
442
443
### Text Formatting and Utilities
444
445
Helper methods for text processing and formatting.
446
447
```python { .api }
448
def title(self, value):
449
"""
450
Apply title casing based on is_title setting.
451
452
Parameters:
453
- value: str - Text to potentially title-case
454
455
Returns:
456
str - Formatted text
457
"""
458
459
def inflect(self, value, text):
460
"""
461
Basic pluralization for currency and other forms.
462
463
Parameters:
464
- value: int - Number for pluralization decision
465
- text: str - Text with plural forms (format: "singular/plural")
466
467
Returns:
468
str - Appropriately inflected text
469
"""
470
471
def parse_minus(self, num_str):
472
"""
473
Extract minus sign from number string.
474
475
Parameters:
476
- num_str: str - Number string that may start with '-'
477
478
Returns:
479
tuple - (minus_prefix, cleaned_number_string)
480
"""
481
```
482
483
### Abstract Methods
484
485
Methods that must be implemented by language subclasses.
486
487
```python { .api }
488
def pluralize(self, n, forms):
489
"""
490
Language-specific pluralization rules.
491
492
Must be implemented by language subclasses.
493
494
Parameters:
495
- n: int - Number for pluralization decision
496
- forms: tuple - Available forms for pluralization
497
498
Returns:
499
str - Correctly pluralized form
500
501
Raises:
502
NotImplementedError - If not implemented by subclass
503
"""
504
505
def merge(self, curr, next):
506
"""
507
Language-specific number component merging.
508
509
Must be implemented by language subclasses.
510
511
Parameters:
512
- curr: tuple - Current number component
513
- next: tuple - Next number component
514
515
Returns:
516
tuple - Merged component
517
518
Raises:
519
NotImplementedError - If not implemented by subclass
520
"""
521
```
522
523
## Inheritance Hierarchy
524
525
The language converters follow a clear inheritance pattern:
526
527
```python
528
# Base class
529
Num2Word_Base
530
├── Num2Word_EU (European base class)
531
│ ├── Num2Word_EN (English)
532
│ │ ├── Num2Word_EN_IN (English India)
533
│ │ └── Num2Word_EN_NG (English Nigeria)
534
│ ├── Num2Word_FR (French)
535
│ │ ├── Num2Word_FR_BE (French Belgium)
536
│ │ ├── Num2Word_FR_CH (French Switzerland)
537
│ │ └── Num2Word_FR_DZ (French Algeria)
538
│ ├── Num2Word_ES (Spanish)
539
│ │ ├── Num2Word_ES_CO (Spanish Colombia)
540
│ │ ├── Num2Word_ES_CR (Spanish Costa Rica)
541
│ │ └── ...
542
│ └── ... (other European languages)
543
├── Num2Word_AR (Arabic)
544
├── Num2Word_JA (Japanese)
545
├── Num2Word_KO (Korean)
546
└── ... (other non-European languages)
547
```
548
549
## Configuration Attributes
550
551
Each converter can be configured with various attributes:
552
553
```python { .api }
554
class ConverterAttributes:
555
"""Common configuration attributes for converters."""
556
557
# Text formatting
558
is_title: bool = False # Enable title casing
559
exclude_title: list = [] # Words to exclude from title casing
560
561
# Number representation
562
negword: str = "(-) " # Negative number prefix
563
pointword: str = "(.)" # Decimal point representation
564
precision: int = 2 # Decimal precision
565
566
# Currency support
567
CURRENCY_FORMS: dict = {} # Currency name forms
568
CURRENCY_ADJECTIVES: dict = {} # Currency adjectives
569
570
# Number limits
571
MAXVAL: int # Maximum supported number
572
573
# Error messages
574
errmsg_nonnum: str # Non-numeric input error
575
errmsg_floatord: str # Float ordinal error
576
errmsg_negord: str # Negative ordinal error
577
errmsg_toobig: str # Number too large error
578
```
579
580
## Error Handling
581
582
The base converter provides standardized error handling:
583
584
```python
585
# Type validation
586
converter = CONVERTER_CLASSES['en']
587
588
try:
589
converter.to_ordinal(42.5) # Floats not allowed for ordinals
590
except TypeError as e:
591
print(e) # "Cannot treat float 42.5 as ordinal."
592
593
try:
594
converter.to_ordinal(-5) # Negative numbers not allowed for ordinals
595
except TypeError as e:
596
print(e) # "Cannot treat negative num -5 as ordinal."
597
598
# Overflow protection
599
try:
600
converter.to_cardinal(10**100) # Exceeds MAXVAL
601
except OverflowError as e:
602
print(e) # "abs(value) must be less than MAXVAL."
603
```