spellmoney
Convierte montos numéricos a letras, con el formato exacto que exigen los documentos legales y financieros — cheques, facturas, recibos y contratos: CIENTO VEINTICINCO DÓLARES CON 50/100.
▶ Probalo en el navegador · Read this in English
Existe también el puerto a TypeScript/JavaScript — misma lógica, mismos datos de moneda, mismo resultado exacto.
Instalación
pip install spellmoney
Uso
from spellmoney import a_letras
a_letras(125.50)
# 'CIENTO VEINTICINCO DÓLARES CON 50/100'
a_letras("125.50")
# 'CIENTO VEINTICINCO DÓLARES CON 50/100' (lectura decimal exacta)
a_letras(1, moneda="GTQ")
# 'UN QUETZAL CON 00/100'
a_letras(21000000, moneda="EUR")
# 'VEINTIÚN MILLONES DE EUROS CON 00/100'
a_letras(2, moneda="GBP", mayusculas=False)
# 'dos libras esterlinas con 00/100'
a_letras(10.50, centavos="palabras")
# 'DIEZ DÓLARES CON CINCUENTA CENTAVOS'
Otros idiomas
a_letras(125.50, idioma="en")
# 'ONE HUNDRED TWENTY-FIVE DOLLARS AND 50/100'
a_letras(125.50, idioma="pt", moneda="BRL")
# 'CENTO E VINTE E CINCO REAIS E 50/100'
a_letras(125.50, idioma="fr", moneda="EUR")
# 'CENT VINGT-CINQ EUROS ET 50/100'
Desde la terminal
spellmoney 125.50
spellmoney 125.50 --moneda GTQ
spellmoney 1000000 --moneda EUR --idioma fr
spellmoney --monedas quetzal
Solo el número, sin moneda
from spellmoney import (
numero_a_letras,
numero_a_letras_en,
numero_a_letras_pt,
numero_a_letras_fr,
)
numero_a_letras(1000000) # 'un millón'
numero_a_letras(1000000000) # 'mil millones' (¡no "un billón"!)
numero_a_letras(1000000000000) # 'un billón'
numero_a_letras(200, "f") # 'doscientas' (concordancia de género)
numero_a_letras_en(1000000000) # 'one billion' (escala corta del inglés)
numero_a_letras_pt(21, "f") # 'vinte e uma' (concordancia de género)
numero_a_letras_fr(71) # 'soixante et onze' (base vigesimal del francés)
Divisas y subunidades
El catálogo sigue el estándar ISO 4217, incluido el número de decimales de cada divisa. Eso cambia la salida:
a_letras(125.50, moneda="JPY")
# 'CIENTO VEINTISÉIS YENES JAPONESES' el yen no tiene subunidad
a_letras("125.500", moneda="KWD")
# 'CIENTO VEINTICINCO DINARES KUWAITÍES CON 500/1000' el dinar se divide en 1000
a_letras(1.25, moneda="GBP", centavos="palabras")
# 'UNA LIBRA ESTERLINA CON VEINTICINCO PENIQUES' no "centavos"
a_letras(1.25, moneda="EUR", centavos="palabras")
# 'UN EURO CON VEINTICINCO CÉNTIMOS'
El género de la divisa arrastra al número, como exige la gramática — y no solo en el último dígito: las centenas concuerdan aunque se interponga "mil".
a_letras(200, moneda="GBP")
# 'DOSCIENTAS LIBRAS ESTERLINAS CON 00/100'
a_letras(200000, moneda="GBP")
# 'DOSCIENTAS MIL LIBRAS ESTERLINAS CON 00/100'
a_letras(200, moneda="USD")
# 'DOSCIENTOS DÓLARES CON 00/100'
a_letras(200000000, moneda="GBP")
# 'DOSCIENTOS MILLONES DE LIBRAS ESTERLINAS CON 00/100' "millones" es masculino
Los cuatro idiomas cubren las 156 divisas del catálogo, cada una con su nombre, su género gramatical y, cuando la tiene, el nombre de su subunidad:
| Idioma | Divisas | Ejemplo |
|---|---|---|
es (español) |
156 | UNA CORONA CHECA CON 00/100 |
en (inglés) |
156 | ONE CZECH KORUNA AND 00/100 |
pt (portugués) |
156 | UMA COROA TCHECA E 00/100 |
fr (francés) |
156 | UNE COURONNE TCHÈQUE ET 00/100 |
Divisas retiradas. Las que el estándar retiró se conservan, marcadas con la fecha en MONEDAS[codigo]["retirada"] — el florín antillano (ANG, 2025-03), el dólar zimbabuense (ZWL, 2024-09) y el lev búlgaro (BGN, 2026-01). Una factura de 2023 se tiene que poder escribir igual.
Montos negativos
Por defecto se rechazan, porque en un cheque casi siempre son un error. Para notas de crédito y devoluciones:
a_letras(-125.50, negativos="prefijo")
# 'MENOS CIENTO VEINTICINCO DÓLARES CON 50/100'
Plantilla de salida
Cada país tiene su fórmula legal. La plantilla permite calcarla:
a_letras(125.50, plantilla="SON: {monto} {moneda} {conector} {centavos}")
# 'SON: CIENTO VEINTICINCO DÓLARES CON 50/100'
a_letras(125.50, plantilla="{monto} {moneda} ({codigo})")
# 'CIENTO VEINTICINCO DÓLARES (USD)'
Marcadores disponibles: {signo}, {monto}, {moneda}, {conector}, {centavos} y {codigo}. Los espacios sobrantes se colapsan.
Ojo con mayusculas: pasa todo el resultado a mayúsculas o a minúsculas, la plantilla incluida. No conserva el texto tal como se escribió.
API
| Función | Descripción |
|---|---|
a_letras(monto, ...) |
Convierte un monto con nombre de moneda. |
numero_a_letras(n, genero="m") |
Solo el número, en español. |
numero_a_letras_en(n) |
Solo el número, en inglés. |
numero_a_letras_pt(n, genero="m") |
Solo el número, en portugués. |
numero_a_letras_fr(n) |
Solo el número, en francés. |
MONEDAS |
Catálogo de divisas ISO 4217, con decimales y subunidades. |
IDIOMAS |
("es", "en", "pt", "fr"). |
SpellMoneyError |
Error lanzado ante un monto, moneda o idioma inválidos. |
Parámetros de a_letras:
| Parámetro | Valores | Por defecto |
|---|---|---|
monto |
int, float, Decimal o cadena decimal |
— |
moneda |
código ISO 4217 | "USD" |
idioma |
"es", "en", "pt", "fr" |
"es" |
centavos |
"fraccion", "palabras" |
"fraccion" |
mayusculas |
bool |
True |
negativos |
"error", "prefijo" |
"error" |
plantilla |
str |
según la divisa |
Redondeo y precisión
Un monto se puede pasar como float, como Decimal o como cadena decimal, y la diferencia importa:
- Cadena o
Decimal—a_letras("125.50"),a_letras(Decimal("125.50")): los dígitos se leen tal como fueron escritos, sin pasar por punto flotante. El redondeo del primer decimal sobrante es half-up exacto, así que"2.675"da68/100. Es la vía recomendada cuando el monto viene de una base de datos, un formulario o un archivo. float—a_letras(125.50): los montos de dos decimales se convierten de forma exacta. Verificado sobre el millón de montos de0.00a9999.99: ninguna diferencia frente a aritmética decimal exacta. Con tres o más decimales, el empate exacto se resuelve según el valor binario que elfloatalmacena realmente, que puede quedar apenas por debajo del decimal escrito:2.675da67/100. Es una propiedad del tipofloat, no de esta librería.
Rango soportado
Enteros de 0 a 999,999,999,999,999. Un monto fuera de ese rango lanza SpellMoneyError, igual que una moneda no reconocida o un idioma no soportado.
Desarrollo
git clone https://github.com/brandriver-bit/spellmoney.git
cd spellmoney
pip install -e ".[dev]"
pytest
Licencia
MIT — ver LICENSE.
spellmoney (English)
Turns numeric amounts into words, in the exact format legal and financial documents require — cheques, invoices, receipts and contracts: ONE HUNDRED TWENTY-FIVE DOLLARS AND 50/100.
▶ Try it in your browser · Leer esto en español
Four languages — Spanish, English, Brazilian Portuguese and French — and the ISO 4217 currency catalog, including each currency's minor units. Zero dependencies. There is also a TypeScript/JavaScript port with identical output.
Install
pip install spellmoney
Usage
from spellmoney import a_letras
a_letras(125.50, idioma="en")
# 'ONE HUNDRED TWENTY-FIVE DOLLARS AND 50/100'
a_letras("125.50", idioma="en", moneda="GBP", centavos="palabras")
# 'ONE HUNDRED TWENTY-FIVE POUNDS STERLING AND FIFTY PENCE'
a_letras(125.50, idioma="en", moneda="JPY")
# 'ONE HUNDRED TWENTY-SIX JAPANESE YEN' the yen has no minor unit
a_letras("125.500", idioma="en", moneda="KWD")
# 'ONE HUNDRED TWENTY-FIVE KUWAITI DINARS AND 500/1000'
There's also a CLI:
spellmoney 125.50 --idioma en --moneda GBP
The API is in Spanish because that's the audience it was written for. a_letras(amount, ...) is the entry point; moneda is the ISO 4217 code, idioma the language, centavos whether the minor unit is written as a fraction (50/100) or in words, mayusculas the casing, negativos how to treat negative amounts, and plantilla an output template for matching a specific legal wording.
Pass the amount as a string or a Decimal to have its digits read exactly, without floating point: "2.675" rounds half-up to 68/100, while the float 2.675 gives 67/100 because the nearest double sits just below it.
All four languages cover every currency in the catalog, each with its name, grammatical gender and, where it has one, the name of its minor unit. Withdrawn currencies are kept and flagged with the date they left the standard, so older documents can still be spelled.
MIT licensed.
Metadata
Release files for spellmoney 2.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| spellmoney-2.0.0.tar.gz | 35.7 kB | Without provenance | Details for spellmoney-2.0.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| spellmoney-2.0.0-py3-none-any.whl | Python 3 | none | any | Details for spellmoney-2.0.0-py3-none-any.whl |
Total release size: 64.1 kB
Release files / spellmoney-2.0.0.tar.gz
| Download URL | spellmoney-2.0.0.tar.gz |
|---|---|
| Size | 35.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ec732daf1317c9fc8011cdde6b20c47938bd528cebfbc1ddae4c683e27327e44
|
|
BLAKE2b-256 checksum How to use checksums |
fbe87377a9b9f392a60debafc1c5ee5a3552ab3bd6c2f9f7c8dedf8f4252bfbd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.10
|
Release files / spellmoney-2.0.0-py3-none-any.whl
| Download URL | spellmoney-2.0.0-py3-none-any.whl |
|---|---|
| Size | 28.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b1d257ac319aa89963c6d8e47e8ab8395582851cc0d957e4b69501771b56decf
|
|
BLAKE2b-256 checksum How to use checksums |
4af2ebc1dbc10dac6111b07f423af4d758a2b8798e4822aae06905d58081a4ad
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.10
|
Security for spellmoney 2.0.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.