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.2.tar.gz (151.4 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.2-py3-none-any.whl (79.5 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: i18n_modern-0.2.2.tar.gz
  • Upload date:
  • Size: 151.4 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.2.tar.gz
Algorithm Hash digest
SHA256 bbb2ee0beb52cf6bc21e0f0213f928ad765aff65802355d1752b8503ef4b52ec
MD5 25fefc361be10b12b4b981f25a61ae57
BLAKE2b-256 be1d8d4aa49e7843ced27c63ce5ea8bdb0b6f6cfd0a9c3e57b96d2d70fe23bd7

See more details on using hashes here.

File details

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

File metadata

  • Download URL: i18n_modern-0.2.2-py3-none-any.whl
  • Upload date:
  • Size: 79.5 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.2-py3-none-any.whl
Algorithm Hash digest
SHA256 e108b4254cb70dcfda006b6b852f6564884ba1451fcd829c61de36bbbdaac668
MD5 fbb300677f2731570df2528cfc8f3ea2
BLAKE2b-256 113ab4cab2114b9eafd25f96a3f8f30e082a5daf93283c410acfba90314b8d4c

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