Python library for loading localizations with dot access and pluralization.
Project description
Type-safe localization library for Python.
Access YAML, JSON, and XML translations using dot-notation.
Overview
doti18n allows you to replace string-based dictionary lookups with intuitive object navigation. Instead of locales['en']['messages']['error'], just write locales["en"].messages.error.
It focuses on Developer Experience (DX) by providing a CLI tool to generate .pyi stubs. This enables IDE autocompletion and allows static type checkers (mypy, pyright) to catch missing keys at build time.
Key Features
- Dot-Notation: Access nested keys via attributes (
data.key) and lists via indices (items[0]). - Type Safety: Generate stubs to get full IDE support and catch typos instantly.
- Advanced ICUMF: Full support for ICU Message Format including nested
select,plural, and custom formatters. - Pluralization: Robust support powered by Babel.
- Format Agnostic: Supports YAML, JSON, and XML out of the box.
- Safety Modes:
- Strict: Raises exceptions for missing keys (good for dev/test).
- Non-strict: Returns a safe wrapper and logs warnings (good for production).
- Fallback: Automatically falls back to the default locale if a key is missing.
Installation
pip install doti18n
If you use YAML files:
pip install doti18n[yaml]
Usage
1. Create a localization file (locales/en.yaml):
greeting: "Hello {}!"
farewell: "Goodbye $name!"
items:
- name: "Item 1"
- name: "Item 2"
# Basic key-based pluralization
notifications:
one: "You have {count} new notification."
other: "You have {count} new notifications."
# Complex ICU Message Format (Nesting + Select + Plural)
loot_msg: |
{hero} found {type, select,
weapon {{count, plural, one {a legendary sword} other {# rusty swords}}}
potion {{count, plural, one {a healing potion} other {# healing potions}}}
other {{count} items}
} in the chest.
2. Access it in Python:
from doti18n import LocaleData
# Initialize (loads and caches data)
i18n = LocaleData("locales")
en = i18n["en"]
# 1. Standard formatting (Python-style)
print(en.greeting("John")) # Output: Hello John!
# 2. Variable formatting (Shell-style)
print(en.farewell(name="Alice")) # Output: Goodbye Alice!
# 3. Raw strings and graceful handling
print(en.farewell) # Output: Goodbye $name! (Raw string)
print(en.farewell()) # Output: Goodbye ! (Missing var handled)
# 4. List access
print(en.items[0].name) # Output: Item 1
# 5. Basic Pluralization
print(en.notifications(1)) # Output: You have 1 new notification.
# 6. Advanced ICUMF Logic
# "weapon" branch -> "one" sub-branch
print(en.loot_msg(hero="Arthur", type="weapon", count=1))
# Output: Arthur found a legendary sword in the chest.
# "potion" branch -> "other" sub-branch
print(en.loot_msg(hero="Merlin", type="potion", count=5))
# Output: Merlin found 5 healing potions in the chest.
CLI & Type Safety
doti18n comes with a CLI to generate type stubs (.pyi).
Why use it?
- Autocompletion: Your IDE will suggest available keys as you type.
- Validation: Static analysis tools will flag errors if you try to access a key that doesn't exist.
- Deep ICUMF Introspection: The generator parses complex ICUMF strings (like the
loot_msgexample above) and creates precise function signatures.- Example: For
loot_msg, it generates:def loot_msg(self, *, hero: str, type: str, count: int) -> str. - Your IDE will tell you exactly which arguments are required, even for deeply nested logic.
- Example: For
Commands:
# Generate stubs for all files in 'locales/' (default lang: en)
python -m doti18n stub locales/
# Generate stubs with a specific default language
python -m doti18n stub locales/ -lang fr
# Clean up generated stubs
python -m doti18n stub --clean
Note: Run this inside your virtual environment to ensure stubs are generated for the installed package.
Project Status
Alpha Stage: The API is stable but may evolve before the 1.0.0 release. Feedback and feature requests are highly appreciated!
Documentation
Documentation is available at:
https://darkj3suss.github.io/doti18n/
License
MIT License. See LICENSE for details.
Contact
- Issues: GitHub Issues
- Direct: Telegram
Project details
Release history Release notifications | RSS feed
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 doti18n-0.6.0.tar.gz.
File metadata
- Download URL: doti18n-0.6.0.tar.gz
- Upload date:
- Size: 37.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0ff9f08e6378ff42c0525c831041845f1ddbdee0ed12f62329d7de0296bcdad5
|
|
| MD5 |
53cef9b46ce5ca44a0d3d2e0448903b1
|
|
| BLAKE2b-256 |
a7ecad5d4235979c26d0a19ccaf5afdb71f3539f260a0eeb218961220cfea920
|
Provenance
The following attestation bundles were made for doti18n-0.6.0.tar.gz:
Publisher:
python-publish.yml on darkj3suss/doti18n
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
doti18n-0.6.0.tar.gz -
Subject digest:
0ff9f08e6378ff42c0525c831041845f1ddbdee0ed12f62329d7de0296bcdad5 - Sigstore transparency entry: 889450479
- Sigstore integration time:
-
Permalink:
darkj3suss/doti18n@4c2ad42f75aa4168516791ffab416546304fe660 -
Branch / Tag:
refs/tags/v0.6.0 - Owner: https://github.com/darkj3suss
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@4c2ad42f75aa4168516791ffab416546304fe660 -
Trigger Event:
push
-
Statement type:
File details
Details for the file doti18n-0.6.0-py3-none-any.whl.
File metadata
- Download URL: doti18n-0.6.0-py3-none-any.whl
- Upload date:
- Size: 53.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b998a03e578e16622a9020bc67d77c649a17c97b2aa59282cf15114773932cbf
|
|
| MD5 |
50aa268af29bf5a0d41bf8829d1a3d8f
|
|
| BLAKE2b-256 |
530501b926869ce0517a0b4d770a884b1c99cd48cb680f58a4a74676df0a881b
|
Provenance
The following attestation bundles were made for doti18n-0.6.0-py3-none-any.whl:
Publisher:
python-publish.yml on darkj3suss/doti18n
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
doti18n-0.6.0-py3-none-any.whl -
Subject digest:
b998a03e578e16622a9020bc67d77c649a17c97b2aa59282cf15114773932cbf - Sigstore transparency entry: 889450515
- Sigstore integration time:
-
Permalink:
darkj3suss/doti18n@4c2ad42f75aa4168516791ffab416546304fe660 -
Branch / Tag:
refs/tags/v0.6.0 - Owner: https://github.com/darkj3suss
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@4c2ad42f75aa4168516791ffab416546304fe660 -
Trigger Event:
push
-
Statement type: