Skip to main content

Python library for loading localizations with dot access and pluralization.

Project description

PyPI version License

doti18n
Modern, type-safe i18n / l10n library for Python.
The alternative to standart i18n libraries with dot-notation, ICU Message Format, IDE autocompletion and powerful CLI.

Overview

doti18n allows you to replace string-based dictionary lookups with intuitive object navigation. Instead of i18n["en"]["messages"]["error"], just write i18n["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, typo and type mismatching 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, XML, TOML 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.
  • Macros: Define reusable snippets for common patterns (e.g., reusable gender-select ICU snippets).
  • Powerful CLI: Generate stubs, lint for missing keys and run a web-based translation studio.

Installation

Requires Python 3.11+

pip install doti18n

If you use YAML files:

pip install doti18n[yaml]

Usage

1. Create a localization file (locales/en.yaml):

__macros__: # Define a section with macros
    gender: {gender, select, male {He} female {She} other {They}}

greeting: "Hello {}!"
farewell: "Goodbye {name}!"

# Using macros
user_action: "@gender uploaded a new photo."
user_status: "@gender is currently online."

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!
print(en.farewell(name="Alice"))        # Output: Goodbye Alice!

# 2. Raw strings and graceful handling
print(en.farewell)                      # Output: Goodbye {name}! (Raw string)
print(en.farewell())                    # Output: Goodbye ! (Missing var handled)

# 3. Using strings with macros
print(en.user_action(gender="male"))    # Output: He uploaded a new photo.
print(en.user_status(gender="female"))  # Output: She is currently online.

# 4. List access
print(en.items[0].name)                 # Output: Item 1

# 5. Basic Pluralization
print(en.notifications(1))              # Output: You have 1 new notification.
print(en.notifications(5))              # Output: You have 5 new notifications.

# 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

Stub Generation / Type Safety

doti18n comes with a CLI to generate type stubs (.pyi).

Why use it?

  1. Autocompletion: Your IDE will suggest available keys as you type.
  2. Validation: Static analysis tools will flag errors if you try to access a key that doesn't exist.
  3. Deep ICUMF Introspection: The generator parses complex ICUMF strings (like the loot_msg example 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.

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.

Lint

Scan your translation files for missing keys, type mismatches and structural issues across locales.

# Lint all locales against the default language (en)
doti18n lint locales/

# Lint against a specific source language
doti18n lint locales/ -lang fr

Studio

A web-based translation editor that runs locally. It lets you browse, edit and save translations in real time from the browser. Multiple users can work simultaneously — edits are synced via WebSocket.

Studio requires extra dependencies:

pip install doti18n[studio]

First, create a user:

doti18n studio add-user admin password

Then start the server:

doti18n studio run locales/

Open http://127.0.0.1:5000, log in, and you'll see all your locales and keys ready to edit.

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 darkj3suss.github.io/doti18n.

License

MIT License. See LICENSE for details.

Contact

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

doti18n-0.10.2.tar.gz (60.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

doti18n-0.10.2-py3-none-any.whl (84.6 kB view details)

Uploaded Python 3

File details

Details for the file doti18n-0.10.2.tar.gz.

File metadata

  • Download URL: doti18n-0.10.2.tar.gz
  • Upload date:
  • Size: 60.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for doti18n-0.10.2.tar.gz
Algorithm Hash digest
SHA256 414125d1e711fac4530d1945606ea4d35c7ad74adf27ac38cfe6d89c92cc0c62
MD5 3a2694bd3eedf51b287c4a4c167ad68b
BLAKE2b-256 6e37ae1f5e00fc0c6ecb18c032236e2cabf1fa4c6f87fb069fc3f731864b37da

See more details on using hashes here.

Provenance

The following attestation bundles were made for doti18n-0.10.2.tar.gz:

Publisher: python-publish.yml on darkj3suss/doti18n

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file doti18n-0.10.2-py3-none-any.whl.

File metadata

  • Download URL: doti18n-0.10.2-py3-none-any.whl
  • Upload date:
  • Size: 84.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for doti18n-0.10.2-py3-none-any.whl
Algorithm Hash digest
SHA256 2cf3a3ed9a5aff940608f7367c10a502a1648fbaa24b0088395fbd18420027c7
MD5 77949b56be08d06ed01e62f1fd9e3182
BLAKE2b-256 154a95bb9fe296df366630d14c90d373e8f652bafe8e172f560b553003df320b

See more details on using hashes here.

Provenance

The following attestation bundles were made for doti18n-0.10.2-py3-none-any.whl:

Publisher: python-publish.yml on darkj3suss/doti18n

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page