Claude Code for num2words: Numbers to Words in Python — Claude Skills 360 Blog
Blog / AI / Claude Code for num2words: Numbers to Words in Python
AI

Claude Code for num2words: Numbers to Words in Python

Published: February 26, 2028
Read time: 5 min read
By: Claude Skills 360

num2words converts numbers to their word representations. pip install num2words. Basic: from num2words import num2words. num2words(42) → “forty-two”. num2words(1234567) → “one million, two hundred and thirty-four thousand, five hundred and sixty-seven”. Ordinal: num2words(3, to="ordinal") → “third”. num2words(21, to="ordinal") → “twenty-first”. Ordinal num: num2words(21, to="ordinal_num") → “21st”. Year: num2words(1999, to="year") → “nineteen ninety-nine”. Currency: num2words(1234.56, to="currency", lang="en_GB") → “one thousand, two hundred and thirty-four pounds, fifty-six pence”. Lang: num2words(42, lang="de") → “zweiundvierzig”. num2words(42, lang="fr") → “quarante-deux”. num2words(42, lang="es") → “cuarenta y dos”. num2words(42, lang="ru") → “сорок два”. num2words(42, lang="ar") → Arabic text. num2words(42, lang="ja") → “四十二”. Available: en en_GB de fr es it pt ru tr ar uk ko ja zh. Negative: num2words(-5) → “minus five”. Float: num2words(3.14) → “three point one four”. num2words(0.5) → “zero point five”. Currency with denominator: num2words(10.50, to="currency", currency="USD"). Claude Code generates num2words converters, invoice amount writers, and multilingual number renderers.

CLAUDE.md for num2words

## num2words Stack
- Version: num2words >= 0.5.13 | pip install num2words
- Cardinal: num2words(1234) → "one thousand two hundred and thirty-four"
- Ordinal: num2words(3, to="ordinal") → "third" | to="ordinal_num" → "3rd"
- Year: num2words(1999, to="year") → "nineteen ninety-nine"
- Currency: num2words(99.50, to="currency", lang="en_GB") — amount in words
- Lang: lang="de"/"fr"/"es"/"ru"/"ar"/"ja" — 40+ languages supported
- Jinja2: env.filters["num2words"] = lambda n, **kw: num2words(n, **kw)

num2words Number-to-Words Pipeline

# app/number_words.py — num2words cardinal, ordinal, currency, and multilingual
from __future__ import annotations

from typing import Any

from num2words import num2words, CONVERTER_CLASSES


# ─────────────────────────────────────────────────────────────────────────────
# 1. Core conversion helpers
# ─────────────────────────────────────────────────────────────────────────────

def to_words(number: int | float, lang: str = "en") -> str:
    """
    Convert a number to its cardinal word form.
    num2words(1234567) → "one million, two hundred and thirty-four thousand,
                          five hundred and sixty-seven"
    """
    return num2words(number, lang=lang)


def to_ordinal(number: int, lang: str = "en") -> str:
    """
    Convert a number to its ordinal word form.
    to="ordinal": 3 → "third", 21 → "twenty-first"
    Supports ordinal in German (dritte), French (troisième), Spanish (tercero), etc.
    """
    return num2words(number, to="ordinal", lang=lang)


def to_ordinal_num(number: int, lang: str = "en") -> str:
    """
    Convert a number to ordinal numeral form (suffix style).
    to="ordinal_num": 1 → "1st", 2 → "2nd", 21 → "21st"
    """
    return num2words(number, to="ordinal_num", lang=lang)


def to_year(year: int, lang: str = "en") -> str:
    """
    Convert a year to its spoken form.
    1999 → "nineteen ninety-nine"
    2024 → "twenty twenty-four"
    1900 → "nineteen hundred"
    """
    return num2words(year, to="year", lang=lang)


def to_currency_words(
    amount: float,
    currency: str = "USD",
    lang: str = "en",
) -> str:
    """
    Convert a monetary amount to words.
    Used on checks, invoices, and legal documents.
    98.50 USD → "ninety-eight dollars, fifty cents"
    1234.56 EUR → "one thousand, two hundred and thirty-four euros, fifty-six cents"
    """
    return num2words(amount, to="currency", currency=currency, lang=lang)


# ─────────────────────────────────────────────────────────────────────────────
# 2. Invoice / check amount formatter
# ─────────────────────────────────────────────────────────────────────────────

def invoice_amount_words(
    amount: float,
    currency: str = "USD",
    lang: str = "en",
    capitalize: bool = True,
) -> str:
    """
    Format an invoice amount as words for check writing or legal documents.
    Returns e.g. "One Thousand Two Hundred Forty-Five Dollars and 50/100"
    """
    words = to_currency_words(amount, currency=currency, lang=lang)
    if capitalize:
        words = words.capitalize()

    # Add "and XX/100" suffix common on US checks
    if lang == "en" and currency in ("USD", "CAD"):
        cents = round((amount % 1) * 100)
        # Remove the "cents" part from num2words and replace with xx/100
        # num2words format: "X dollars, Y cents" → strip after comma
        if "," in words:
            dollar_part = words.split(",")[0]
            return f"{dollar_part} and {cents:02d}/100"

    return words


def check_line(amount: float, currency: str = "USD") -> str:
    """Format a check amount line: '**One Thousand Two Hundred and 50/100**'"""
    words = invoice_amount_words(amount, currency=currency)
    return f"**{words}**"


# ─────────────────────────────────────────────────────────────────────────────
# 3. Multilingual number conversion
# ─────────────────────────────────────────────────────────────────────────────

SUPPORTED_LANGS = sorted(CONVERTER_CLASSES.keys())


def to_words_multilingual(number: int | float) -> dict[str, str]:
    """
    Convert a number to words in all supported languages.
    Returns {lang_code: word_string}.
    """
    results = {}
    for lang in SUPPORTED_LANGS:
        try:
            results[lang] = num2words(number, lang=lang)
        except Exception:
            pass
    return results


def to_words_langs(number: int | float, langs: list[str]) -> dict[str, str]:
    """Convert a number to words in a specific list of languages."""
    results = {}
    for lang in langs:
        try:
            results[lang] = num2words(number, lang=lang)
        except Exception as e:
            results[lang] = f"(error: {e})"
    return results


# ─────────────────────────────────────────────────────────────────────────────
# 4. Ordinal suffix helper (for format strings)
# ─────────────────────────────────────────────────────────────────────────────

def ordinal_suffix(n: int) -> str:
    """
    Return the ordinal suffix for an integer: 1 → "st", 2 → "nd", 3 → "rd", 4+ → "th".
    This is the English-only quick version; use num2words for international ordinals.
    """
    if 11 <= (n % 100) <= 13:
        return "th"
    return {1: "st", 2: "nd", 3: "rd"}.get(n % 10, "th")


def with_ordinal_suffix(n: int) -> str:
    """Return e.g. '21st', '22nd', '3rd', '11th'."""
    return f"{n}{ordinal_suffix(n)}"


# ─────────────────────────────────────────────────────────────────────────────
# 5. Sequence word generators
# ─────────────────────────────────────────────────────────────────────────────

def ordinal_list(n: int, lang: str = "en") -> list[str]:
    """Return ordinal words for 1..n: ["first", "second", ..., "nth"]."""
    return [num2words(i, to="ordinal", lang=lang) for i in range(1, n + 1)]


def numbered_items(items: list[str], lang: str = "en") -> list[str]:
    """Prefix list items with their ordinal number in words."""
    return [
        f"{num2words(i, to='ordinal', lang=lang).capitalize()}: {item}"
        for i, item in enumerate(items, 1)
    ]


# ─────────────────────────────────────────────────────────────────────────────
# 6. Jinja2 filter registration
# ─────────────────────────────────────────────────────────────────────────────

def register_num2words_filters(env) -> None:
    """
    Register num2words as Jinja2 filters.
    Template usage:
      {{ invoice.total | currency_words("USD") }}
      {{ rank | ordinal }}
      {{ year | year_words }}
      {{ 42 | n2w }}
    """
    env.filters["n2w"]           = lambda n, lang="en": to_words(n, lang=lang)
    env.filters["ordinal"]       = lambda n, lang="en": to_ordinal(n, lang=lang)
    env.filters["ordinal_num"]   = lambda n: to_ordinal_num(n)
    env.filters["year_words"]    = lambda y, lang="en": to_year(y, lang=lang)
    env.filters["currency_words"] = lambda n, curr="USD", lang="en": to_currency_words(n, currency=curr, lang=lang)


# ─────────────────────────────────────────────────────────────────────────────
# Demo
# ─────────────────────────────────────────────────────────────────────────────

if __name__ == "__main__":
    print("=== Cardinal numbers ===")
    for n in [0, 1, 13, 42, 100, 1_000, 1_234_567, -7, 3.14]:
        print(f"  {str(n):12}{num2words(n)}")

    print("\n=== Ordinals (en) ===")
    for n in [1, 2, 3, 4, 11, 12, 13, 21, 22, 100]:
        print(f"  {n:5} → ordinal={num2words(n, to='ordinal'):20}  "
              f"ordinal_num={num2words(n, to='ordinal_num')}")

    print("\n=== Years ===")
    for y in [1066, 1776, 1900, 1999, 2000, 2024]:
        print(f"  {y}{num2words(y, to='year')}")

    print("\n=== Currencies ===")
    amounts = [(99.50, "USD", "en"), (1234.56, "EUR", "de"),
               (9999.99, "GBP", "en_GB"), (500.00, "JPY", "ja")]
    for amount, curr, lang in amounts:
        print(f"  {amount} {curr}/{lang:6}{to_currency_words(amount, currency=curr, lang=lang)}")

    print("\n=== Invoice check line ===")
    for amount in [99.50, 1_234.56, 100_000.00]:
        print(f"  ${amount:>12,.2f}{check_line(amount)}")

    print("\n=== Multilingual (42) ===")
    DEMO_LANGS = ["en", "de", "fr", "es", "it", "ru", "ar", "ja", "ko", "zh"]
    ml = to_words_langs(42, DEMO_LANGS)
    for lang, words in ml.items():
        print(f"  {lang:5}{words}")

    print("\n=== Ordinal list (first 5) ===")
    for w in ordinal_list(5):
        print(f"  {w}")

    print("\n=== Numbered items ===")
    tasks = ["Parse input", "Validate schema", "Process records", "Write output"]
    for item in numbered_items(tasks):
        print(f"  {item}")

For the inflect alternative — inflect handles pluralization, article selection (“a” vs “an”), and some number → word conversion, but its number conversion is limited to English and doesn’t support ordinals in other languages; num2words covers 40+ languages with lang="de"/"fr"/"es"/"ru"/"ja" etc., supports to="ordinal", to="year", and to="currency" formats, and is the standard choice when you need multilingual number text output. For the humanize.apnumber alternative — humanize.apnumber(3) → “three” handles 0–9 in AP style and returns the numeral for 10 and above; num2words handles arbitrarily large integers, floats, negative numbers, ordinals, years, and currencies in 40+ languages — the right choice when “forty-two” or “일천이백삼십사” is what you need. The Claude Skills 360 bundle includes num2words skill sets covering num2words() cardinal conversion, to=“ordinal” for word ordinals, to=“ordinal_num” for suffix ordinals (1st/2nd/3rd), to=“year” for year reading, to=“currency” with currency code, to_words_multilingual() for all languages, to_words_langs() for selected languages, invoice_amount_words() with check format, check_line() formatter, ordinal_suffix() English suffix helper, ordinal_list() generator, numbered_items() list formatter, and Jinja2 filter registration. Start with the free tier to try number-to-words conversion code generation.

Keep Reading

AI

Claude Code for email.contentmanager: Python Email Content Accessors

Read and write EmailMessage body content with Python's email.contentmanager module and Claude Code — email contentmanager ContentManager for the class that maps content types to get and set handler functions allowing EmailMessage to support get_content and set_content with type-specific behaviour, email contentmanager raw_data_manager for the ContentManager instance that handles raw bytes and str payloads without any conversion, email contentmanager content_manager for the standard ContentManager instance used by email.policy.default that intelligently handles text plain text html multipart and binary content types, email contentmanager get_content_text for the handler that returns the decoded text payload of a text-star message part as a str, email contentmanager get_content_binary for the handler that returns the raw decoded bytes payload of a non-text message part, email contentmanager get_data_manager for the get-handler lookup used by EmailMessage get_content to find the right reader function for the content type, email contentmanager set_content text for the handler that creates and sets a text part correctly choosing charset and transfer encoding, email contentmanager set_content bytes for the handler that creates and sets a binary part with base64 encoding and optional filename Content-Disposition, email contentmanager EmailMessage get_content for the method that reads the message body using the registered content manager handlers, email contentmanager EmailMessage set_content for the method that sets the message body and MIME headers in one call, email contentmanager EmailMessage make_alternative make_mixed make_related for the methods that convert a simple message into a multipart container, email contentmanager EmailMessage add_attachment for the method that attaches a file or bytes to a multipart message, and email contentmanager integration with email.message and email.policy and email.mime and io for building high-level email readers attachment extractors text body accessors HTML readers and policy-aware MIME construction pipelines.

5 min read Feb 12, 2029
AI

Claude Code for email.charset: Python Email Charset Encoding

Control header and body encoding for international email with Python's email.charset module and Claude Code — email charset Charset for the class that wraps a character set name with the encoding rules for header encoding and body encoding describing how to encode text for that charset in email messages, email charset Charset header_encoding for the attribute specifying whether headers using this charset should use QP quoted-printable encoding BASE64 encoding or no encoding, email charset Charset body_encoding for the attribute specifying the Content-Transfer-Encoding to use for message bodies in this charset such as QP or BASE64, email charset Charset output_codec for the attribute giving the Python codec name used to encode the string to bytes for the wire format, email charset Charset input_codec for the attribute giving the Python codec name used to decode incoming bytes to str, email charset Charset get_output_charset for returning the output charset name, email charset Charset header_encode for encoding a header string using the charset's header_encoding method, email charset Charset body_encode for encoding body content using the charset's body_encoding, email charset Charset convert for converting a string from the input_codec to the output_codec, email charset add_charset for registering a new charset with custom encoding rules in the global charset registry, email charset add_alias for adding an alias name that maps to an existing registered charset, email charset add_codec for registering a codec name mapping for use by the charset machinery, and email charset integration with email.message and email.mime and email.policy and email.encoders for building international email senders non-ASCII header encoders Content-Transfer-Encoding selectors charset-aware message constructors and MIME encoding pipelines.

5 min read Feb 11, 2029
AI

Claude Code for email.utils: Python Email Address and Header Utilities

Parse and format RFC 2822 email addresses and dates with Python's email.utils module and Claude Code — email utils parseaddr for splitting a display-name plus angle-bracket address string into a realname and email address tuple, email utils formataddr for combining a realname and address string into a properly quoted RFC 2822 address with angle brackets, email utils getaddresses for parsing a list of raw address header strings each potentially containing multiple comma-separated addresses into a list of realname address tuples, email utils parsedate for parsing an RFC 2822 date string into a nine-tuple compatible with time.mktime, email utils parsedate_tz for parsing an RFC 2822 date string into a ten-tuple that includes the UTC offset timezone in seconds, email utils parsedate_to_datetime for parsing an RFC 2822 date string into an aware datetime object with timezone, email utils formatdate for formatting a POSIX timestamp or the current time as an RFC 2822 date string with optional usegmt and localtime flags, email utils format_datetime for formatting a datetime object as an RFC 2822 date string, email utils make_msgid for generating a globally unique Message-ID string with optional idstring and domain components, email utils decode_rfc2231 for decoding an RFC 2231 encoded parameter value into a tuple of charset language and value, email utils encode_rfc2231 for encoding a string as an RFC 2231 encoded parameter value, email utils collapse_rfc2231_value for collapsing a decoded RFC 2231 tuple to a Unicode string, and email utils integration with email.message and email.headerregistry and datetime and time for building address parsers date formatters message-id generators header extractors and RFC-compliant email construction utilities.

5 min read Feb 10, 2029

Put these ideas into practice

Claude Skills 360 gives you production-ready skills for everything in this article — and 2,350+ more. Start free or go all-in.

Back to Blog

Get 360 skills free