slugany
Multi-language slugify with zero dependencies. A simple, MIT-licensed alternative to python-slugify.
Features
- Zero deps — no GPL, no text-unidecode, no UnicodeData beyond the stdlib
- Multi-language — built-in tables for Spanish, Portuguese, German, French, and Italian
- Smart punctuation — normalizes curly quotes, em-dashes, NBSP, zero-width characters, bullets
- Case styles — kebab, snake, camel, pascal, dot, train, filename
- CLI included —
slugany "text"from the terminal with auto-stdin - lru_cache — results cached automatically (maxsize=512)
- Idempotent —
slugify(slugify(x)) == slugify(x)guaranteed - Fully typed — type hints on every public API,
py.typedmarker included - ~550 lines core — auditable, no bloat
Installation
pip install slugany
Requires Python 3.11 or later. No runtime dependencies.
Quickstart
from slugany import slugify
slugify("¡Hola Mundo!") # "hola-mundo"
slugify("Café résumé naïve") # "cafe-resume-naive"
slugify("Ñandú coração") # "nandu-coracao"
slugify("Über Straße", lang="de") # "ueber-strasse"
CLI
slugany "Hello World"
# hello-world
echo "Café" | slugany
# cafe
slugany "hello world" --style camel
# helloWorld
slugany "hello-world-foo" --max-length 10 --word-boundary
# hello-world
Styles
slugify("hello world", style="kebab") # "hello-world"
slugify("hello world", style="snake") # "hello_world"
slugify("hello world", style="camel") # "helloWorld"
slugify("hello world", style="pascal") # "HelloWorld"
slugify("hello world", style="dot") # "hello.world"
slugify("hello world", style="train") # "Hello-World"
slugify("Hello World", style="filename") # "Hello-World"
Languages
slugify("España", lang="es") # "espana"
slugify("Coração", lang="pt") # "coracao"
slugify("Über Straße", lang="de") # "ueber-strasse"
slugify("Cœur", lang="fr") # "coeur"
slugify("Caffè", lang="it") # "caffe"
Advanced
# Stopwords
slugify("the quick brown fox", stopwords=["the", "fox"]) # "quick-brown"
# Custom replacements
slugify("hello world", replacements={"hello": "hi"}) # "hi-world"
# Emoji handling
slugify("Hello \U0001f389 World", emoji_mode="strip") # "hello-world"
slugify("Hello \U0001f389 World", emoji_mode="keep") # "hello-world"
# CSS-safe (prefix digit-leading slugs)
slugify("123 main st", css_safe=True) # "s-123-main-st"
# Fallback for empty results
slugify("!!!", fallback="untitled") # "untitled"
# Unicode preservation
slugify("\u00d1and\u00fa", allow_unicode=True) # "\u00f1and\u00fa"
# Batch processing
from slugany import slugify_batch
slugify_batch(["Hello World", "Caf\u00e9 R\u00e9sum\u00e9"]) # ["hello-world", "cafe-resume"]
# Validation
from slugany import is_slug
is_slug("hello-world") # True
is_slug("hello world") # False
is_slug("hello_world", separator="_") # True
Migration from python-slugify
slugany is designed as a drop-in replacement with keyword-only arguments:
# python-slugify
from slugify import slugify
slugify("Hello World", "_")
# slugany
from slugany import slugify
slugify("Hello World", separator="_")
See the migration guide for full details.
Why slugany?
| Aspect | python-slugify | slugany |
|---|---|---|
| Dependencies | text-unidecode (GPL) | Zero |
| License | GPL | MIT |
| Multi-language | Limited | Built-in tables (es, pt, de, fr, it) |
| Caching | No | lru_cache built-in |
| Core size | ~1000+ lines | ~550 lines |
Documentation
Full documentation is available at mathiaspaulenko.github.io/slugany.
Contributing
Contributions are welcome! See CONTRIBUTING.md for guidelines.
Please read our Code of Conduct before participating in the community.
License
MIT — see LICENSE.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file slugany-0.1.0.tar.gz.
File metadata
- Download URL: slugany-0.1.0.tar.gz
- Upload date:
- Size: 32.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
17733e09f67b6ef2d1549dfafe901fe1e7493311a8b40352674e468a0bc0163e
|
|
| MD5 |
272ba7769af8ae08c26fb4c3a9d7825a
|
|
| BLAKE2b-256 |
501dd7dd4b059385625eb102a4e7d0eda1b3d1c24d5ee0dd5e14ff47819f1679
|
Provenance
The following attestation bundles were made for slugany-0.1.0.tar.gz:
Publisher:
release.yml on MathiasPaulenko/slugany
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
slugany-0.1.0.tar.gz -
Subject digest:
17733e09f67b6ef2d1549dfafe901fe1e7493311a8b40352674e468a0bc0163e - Sigstore transparency entry: 2515462438
- Sigstore integration time:
-
Permalink:
MathiasPaulenko/slugany@45257cfba9118d5d9c15bd3251821ae2bb7fc859 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/MathiasPaulenko
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@45257cfba9118d5d9c15bd3251821ae2bb7fc859 -
Trigger Event:
push
-
Statement type:
File details
Details for the file slugany-0.1.0-py3-none-any.whl.
File metadata
- Download URL: slugany-0.1.0-py3-none-any.whl
- Upload date:
- Size: 13.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f02d5e37850673755096279451096119b245b3e3053bfb8aab4bfec38525ef18
|
|
| MD5 |
60b411f681b3f9839b13e56b7b312c2d
|
|
| BLAKE2b-256 |
9238ad5e27ac3127855beb6d3789d944b32dd57c8f0e9ae897f563b91ffb3622
|
Provenance
The following attestation bundles were made for slugany-0.1.0-py3-none-any.whl:
Publisher:
release.yml on MathiasPaulenko/slugany
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
slugany-0.1.0-py3-none-any.whl -
Subject digest:
f02d5e37850673755096279451096119b245b3e3053bfb8aab4bfec38525ef18 - Sigstore transparency entry: 2515462450
- Sigstore integration time:
-
Permalink:
MathiasPaulenko/slugany@45257cfba9118d5d9c15bd3251821ae2bb7fc859 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/MathiasPaulenko
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@45257cfba9118d5d9c15bd3251821ae2bb7fc859 -
Trigger Event:
push
-
Statement type: