Skip to main content

A modern internationalization library for Python with support for JSON, YAML, and TOML

Project description

Python i18n Modern

A modern internationalization (i18n) library for Python, inspired by i18n_modern for JavaScript.

Features

  • 🌍 Simple and intuitive API for translations
  • 📁 Support for multiple file formats: JSON, YAML, and TOML
  • 🔄 Nested translation keys with dot notation
  • 🎯 Conditional translations based on values
  • 📝 Template string interpolation with [placeholder] syntax
  • 💾 Built-in memoization for better performance
  • 🔗 Deep object merging for locale inheritance
  • ⚡ Flat locale structure for O(1) key lookups at runtime

Performance

Benchmarked against the most popular Python i18n libraries (10,000 iterations, Python 3.12.8):

Operation i18n_modern python-i18n pyi18n-v2 i18nice
Simple key access 0.23µs 0.79µs 0.40µs 1.51µs
Nested key access 0.17µs 66.90µs 0.64µs 1.55µs
Parameter substitution 0.43µs 0.99µs 0.83µs 1.91µs
Conditional logic 0.75µs

384x faster than python-i18n for nested key access. See BENCHMARK_REPORT.md for the full analysis.

Installation

# Basic installation (JSON support only)
pip install i18n_modern

# With YAML support
pip install i18n_modern[yaml]

# With TOML support (Python < 3.11)
pip install i18n_modern[toml]

# With all formats
pip install i18n_modern[all]

Quick Start

Loading from Dictionary

from i18n_modern import I18nModern

locales = {
    "greeting": "Hello, [name]!",
    "items": {
        "0": "No items",
        "1": "One item",
        "default": "[count] items"
    }
}

i18n = I18nModern("en", locales)
print(i18n.get("greeting", values={"name": "World"}))  # Hello, World!

Loading from Files

from i18n_modern import I18nModern

# Load from JSON
i18n = I18nModern("en", "locales/en.json")

# Load from YAML
i18n = I18nModern("es", "locales/es.yaml")

# Load from TOML
i18n = I18nModern("fr", "locales/fr.toml")

Example Files

locales/en.json

{
    "welcome": "Welcome to our app!",
    "greeting": "Hello, [name]!",
    "messages": {
        "success": "Operation successful",
        "error": "An error occurred"
    },
    "items": {
        "0": "No items",
        "1": "One item",
        "default": "[count] items"
    }
}

locales/es.yaml

welcome: "¡Bienvenido a nuestra aplicación!"
greeting: "¡Hola, [name]!"
messages:
  success: "Operación exitosa"
  error: "Ocurrió un error"
items:
  "0": "Sin elementos"
  "1": "Un elemento"
  default: "[count] elementos"

locales/fr.toml

welcome = "Bienvenue dans notre application!"
greeting = "Bonjour, [name]!"

[messages]
success = "Opération réussie"
error = "Une erreur s'est produite"

[items]
"0" = "Aucun élément"
"1" = "Un élément"
default = "[count] éléments"

Usage

Basic Translation

i18n = I18nModern("en", locales)
translation = i18n.get("welcome")

Nested Keys

translation = i18n.get("messages.success")

Template Interpolation

translation = i18n.get("greeting", values={"name": "Alice"})
# Output: Hello, Alice!

Conditional Translations

# Using exact matches
print(i18n.get("items", values={"count": 0}))  # No items
print(i18n.get("items", values={"count": 1}))  # One item
print(i18n.get("items", values={"count": 5}))  # 5 items

# Using comparisons
locales = {
    "age_group": {
        "[age] < 18": "Minor",
        "[age] >= 18": "Adult",
        "default": "Unknown"
    }
}

i18n = I18nModern("en", locales)
print(i18n.get("age_group", values={"age": 15}))  # Minor
print(i18n.get("age_group", values={"age": 25}))  # Adult

Multiple Locales

i18n = I18nModern("en")
i18n.load_from_file("locales/en.json", "en")
i18n.load_from_file("locales/es.json", "es")

# Use default locale (en)
print(i18n.get("greeting", values={"name": "World"}))

# Use specific locale
print(i18n.get("greeting", locale="es", values={"name": "Mundo"}))

Loading from Directory

You can load all translation files from a directory at once. This is useful when you have multiple files for a single locale.

# Structure:
# locales/
# ├── es_MX/
# │   ├── auth.yml
# │   ├── common.yml
# │   ├── document.yml
# │   └── roles.yml

i18n = I18nModern("es_MX")

# Load all files from directory - they will be merged together
# The directory name (es_MX) is used as the locale identifier
i18n.load_from_directory("locales/es_MX")

# Or specify a custom locale identifier
i18n.load_from_directory("locales/es_MX", locale_identify="spanish_mexico")

# Now you can access all translations
print(i18n.get("auth.login"))      # From auth.yml
print(i18n.get("common.welcome"))  # From common.yml
print(i18n.get("document.create")) # From document.yml

Changing Default Locale

i18n.default_locale = "es"
translation = i18n.get("welcome")  # Now uses Spanish

API Reference

I18nModern(default_locale, locales=None)

Constructor for the i18n instance.

  • default_locale (str): The default locale identifier
  • locales (dict or str, optional): Initial locales dictionary or path to locale file

get(key, locale=None, values=None)

Get a translation.

  • key (str): Translation key (supports dot notation)
  • locale (str, optional): Locale override
  • values (dict, optional): Values for placeholder replacement
  • Returns: Translated string

load_from_file(file_path, locale_identify)

Load translations from a file.

  • file_path (str): Path to JSON, YAML, or TOML file
  • locale_identify (str): Locale identifier

load_from_directory(directory_path, locale_identify=None)

Load all translation files from a directory concurrently.

  • directory_path (str): Path to directory containing locale files (JSON, YAML, TOML)
  • locale_identify (str, optional): Locale identifier. If None, uses the directory name
  • All files in the directory are merged together into a single locale entry

Supported file formats in directory: .json, .yaml, .yml, .toml

Example:

i18n = I18nModern("es_MX")
# Loads all .json, .yaml, .yml, and .toml files from the directory
i18n.load_from_directory("locales/es_MX")

# With custom locale identifier
i18n.load_from_directory("locales/es_MX", locale_identify="spanish")

load_from_value(locales, locale_identify)

Load translations from a dictionary.

  • locales (dict): Translations dictionary
  • locale_identify (str): Locale identifier

Properties

  • default_locale: Get or set the default locale

License

MIT

Credits

Inspired by i18n_modern for JavaScript.

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

i18n_modern-0.2.3.tar.gz (152.8 kB view details)

Uploaded Source

Built Distribution

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

i18n_modern-0.2.3-py3-none-any.whl (80.0 kB view details)

Uploaded Python 3

File details

Details for the file i18n_modern-0.2.3.tar.gz.

File metadata

  • Download URL: i18n_modern-0.2.3.tar.gz
  • Upload date:
  • Size: 152.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for i18n_modern-0.2.3.tar.gz
Algorithm Hash digest
SHA256 6f58fb912bc5dceeb451936ee45cf5873542537bb15fb87402116e9552b46a57
MD5 7a33af2016a3aebadc1e78d7a1324f23
BLAKE2b-256 e598cb6e0fb83268ec41aae45b9aabd6c7ef4ad1ecdacad5ef73fe770cb39f5e

See more details on using hashes here.

File details

Details for the file i18n_modern-0.2.3-py3-none-any.whl.

File metadata

  • Download URL: i18n_modern-0.2.3-py3-none-any.whl
  • Upload date:
  • Size: 80.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for i18n_modern-0.2.3-py3-none-any.whl
Algorithm Hash digest
SHA256 2cc84bd8b1d396cf2d2a2dbfe0fac4db517d31b1d942f17412f2417332ed53d4
MD5 09f1d2bf5468c35b35e922979e3adf4f
BLAKE2b-256 eaeba338e90b43128714fba215d92b1d904a23fd5486c9faa2d508023ce2cd01

See more details on using hashes here.

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