# Python i18n Modern
A modern internationalization (i18n) library for Python, inspired by [i18n_modern](https://github.com/UrielCuriel/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
## Installation
```bash
# 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
```python
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
```python
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**
```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**
```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**
```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
```python
i18n = I18nModern("en", locales)
translation = i18n.get("welcome")
```
### Nested Keys
```python
translation = i18n.get("messages.success")
```
### Template Interpolation
```python
translation = i18n.get("greeting", values={"name": "Alice"})
# Output: Hello, Alice!
```
### Conditional Translations
```python
# 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
```python
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.
```python
# 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
```python
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:**
```python
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](https://github.com/UrielCuriel/i18n_modern) for JavaScript.
## Author
Uriel Curiel - [urielcurrel@outlook.com](mailto:urielcurrel@outlook.com)
Raw data
{
"_id": null,
"home_page": null,
"name": "i18n_modern",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "i18n, internationalization, l10n, localization, translation",
"author": null,
"author_email": "Uriel Curiel <urielcurrel@outlook.com>",
"download_url": "https://files.pythonhosted.org/packages/9a/73/839cb695cae40f86ca8fbbc9d2a8266c9bdcbe9bb90e4269c0538b52fb00/i18n_modern-0.2.1.tar.gz",
"platform": null,
"description": "# Python i18n Modern\n\nA modern internationalization (i18n) library for Python, inspired by [i18n_modern](https://github.com/UrielCuriel/i18n_modern) for JavaScript.\n\n## Features\n\n- \ud83c\udf0d Simple and intuitive API for translations\n- \ud83d\udcc1 Support for multiple file formats: JSON, YAML, and TOML\n- \ud83d\udd04 Nested translation keys with dot notation\n- \ud83c\udfaf Conditional translations based on values\n- \ud83d\udcdd Template string interpolation with `[placeholder]` syntax\n- \ud83d\udcbe Built-in memoization for better performance\n- \ud83d\udd17 Deep object merging for locale inheritance\n\n## Installation\n\n```bash\n# Basic installation (JSON support only)\npip install i18n_modern\n\n# With YAML support\npip install i18n_modern[yaml]\n\n# With TOML support (Python < 3.11)\npip install i18n_modern[toml]\n\n# With all formats\npip install i18n_modern[all]\n```\n\n## Quick Start\n\n### Loading from Dictionary\n\n```python\nfrom i18n_modern import I18nModern\n\nlocales = {\n \"greeting\": \"Hello, [name]!\",\n \"items\": {\n \"0\": \"No items\",\n \"1\": \"One item\",\n \"default\": \"[count] items\"\n }\n}\n\ni18n = I18nModern(\"en\", locales)\nprint(i18n.get(\"greeting\", values={\"name\": \"World\"})) # Hello, World!\n```\n\n### Loading from Files\n\n```python\nfrom i18n_modern import I18nModern\n\n# Load from JSON\ni18n = I18nModern(\"en\", \"locales/en.json\")\n\n# Load from YAML\ni18n = I18nModern(\"es\", \"locales/es.yaml\")\n\n# Load from TOML\ni18n = I18nModern(\"fr\", \"locales/fr.toml\")\n```\n\n### Example Files\n\n**locales/en.json**\n```json\n{\n \"welcome\": \"Welcome to our app!\",\n \"greeting\": \"Hello, [name]!\",\n \"messages\": {\n \"success\": \"Operation successful\",\n \"error\": \"An error occurred\"\n },\n \"items\": {\n \"0\": \"No items\",\n \"1\": \"One item\",\n \"default\": \"[count] items\"\n }\n}\n```\n\n**locales/es.yaml**\n```yaml\nwelcome: \"\u00a1Bienvenido a nuestra aplicaci\u00f3n!\"\ngreeting: \"\u00a1Hola, [name]!\"\nmessages:\n success: \"Operaci\u00f3n exitosa\"\n error: \"Ocurri\u00f3 un error\"\nitems:\n \"0\": \"Sin elementos\"\n \"1\": \"Un elemento\"\n default: \"[count] elementos\"\n```\n\n**locales/fr.toml**\n```toml\nwelcome = \"Bienvenue dans notre application!\"\ngreeting = \"Bonjour, [name]!\"\n\n[messages]\nsuccess = \"Op\u00e9ration r\u00e9ussie\"\nerror = \"Une erreur s'est produite\"\n\n[items]\n\"0\" = \"Aucun \u00e9l\u00e9ment\"\n\"1\" = \"Un \u00e9l\u00e9ment\"\ndefault = \"[count] \u00e9l\u00e9ments\"\n```\n\n## Usage\n\n### Basic Translation\n\n```python\ni18n = I18nModern(\"en\", locales)\ntranslation = i18n.get(\"welcome\")\n```\n\n### Nested Keys\n\n```python\ntranslation = i18n.get(\"messages.success\")\n```\n\n### Template Interpolation\n\n```python\ntranslation = i18n.get(\"greeting\", values={\"name\": \"Alice\"})\n# Output: Hello, Alice!\n```\n\n### Conditional Translations\n\n```python\n# Using exact matches\nprint(i18n.get(\"items\", values={\"count\": 0})) # No items\nprint(i18n.get(\"items\", values={\"count\": 1})) # One item\nprint(i18n.get(\"items\", values={\"count\": 5})) # 5 items\n\n# Using comparisons\nlocales = {\n \"age_group\": {\n \"[age] < 18\": \"Minor\",\n \"[age] >= 18\": \"Adult\",\n \"default\": \"Unknown\"\n }\n}\n\ni18n = I18nModern(\"en\", locales)\nprint(i18n.get(\"age_group\", values={\"age\": 15})) # Minor\nprint(i18n.get(\"age_group\", values={\"age\": 25})) # Adult\n```\n\n### Multiple Locales\n\n```python\ni18n = I18nModern(\"en\")\ni18n.load_from_file(\"locales/en.json\", \"en\")\ni18n.load_from_file(\"locales/es.json\", \"es\")\n\n# Use default locale (en)\nprint(i18n.get(\"greeting\", values={\"name\": \"World\"}))\n\n# Use specific locale\nprint(i18n.get(\"greeting\", locale=\"es\", values={\"name\": \"Mundo\"}))\n```\n\n### Loading from Directory\n\nYou can load all translation files from a directory at once. This is useful when you have multiple files for a single locale.\n\n```python\n# Structure:\n# locales/\n# \u251c\u2500\u2500 es_MX/\n# \u2502 \u251c\u2500\u2500 auth.yml\n# \u2502 \u251c\u2500\u2500 common.yml\n# \u2502 \u251c\u2500\u2500 document.yml\n# \u2502 \u2514\u2500\u2500 roles.yml\n\ni18n = I18nModern(\"es_MX\")\n\n# Load all files from directory - they will be merged together\n# The directory name (es_MX) is used as the locale identifier\ni18n.load_from_directory(\"locales/es_MX\")\n\n# Or specify a custom locale identifier\ni18n.load_from_directory(\"locales/es_MX\", locale_identify=\"spanish_mexico\")\n\n# Now you can access all translations\nprint(i18n.get(\"auth.login\")) # From auth.yml\nprint(i18n.get(\"common.welcome\")) # From common.yml\nprint(i18n.get(\"document.create\")) # From document.yml\n```\n\n### Changing Default Locale\n\n```python\ni18n.default_locale = \"es\"\ntranslation = i18n.get(\"welcome\") # Now uses Spanish\n```\n\n## API Reference\n\n### `I18nModern(default_locale, locales=None)`\n\nConstructor for the i18n instance.\n\n- `default_locale` (str): The default locale identifier\n- `locales` (dict or str, optional): Initial locales dictionary or path to locale file\n\n### `get(key, locale=None, values=None)`\n\nGet a translation.\n\n- `key` (str): Translation key (supports dot notation)\n- `locale` (str, optional): Locale override\n- `values` (dict, optional): Values for placeholder replacement\n- Returns: Translated string\n\n### `load_from_file(file_path, locale_identify)`\n\nLoad translations from a file.\n\n- `file_path` (str): Path to JSON, YAML, or TOML file\n- `locale_identify` (str): Locale identifier\n\n### `load_from_directory(directory_path, locale_identify=None)`\n\nLoad all translation files from a directory concurrently.\n\n- `directory_path` (str): Path to directory containing locale files (JSON, YAML, TOML)\n- `locale_identify` (str, optional): Locale identifier. If None, uses the directory name\n- All files in the directory are merged together into a single locale entry\n\n**Supported file formats in directory:** `.json`, `.yaml`, `.yml`, `.toml`\n\n**Example:**\n```python\ni18n = I18nModern(\"es_MX\")\n# Loads all .json, .yaml, .yml, and .toml files from the directory\ni18n.load_from_directory(\"locales/es_MX\")\n\n# With custom locale identifier\ni18n.load_from_directory(\"locales/es_MX\", locale_identify=\"spanish\")\n```\n\n### `load_from_value(locales, locale_identify)`\n\nLoad translations from a dictionary.\n\n- `locales` (dict): Translations dictionary\n- `locale_identify` (str): Locale identifier\n\n### Properties\n\n- `default_locale`: Get or set the default locale\n\n## License\n\nMIT\n\n## Credits\n\nInspired by [i18n_modern](https://github.com/UrielCuriel/i18n_modern) for JavaScript.\n\n## Author\n\nUriel Curiel - [urielcurrel@outlook.com](mailto:urielcurrel@outlook.com)\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "A modern internationalization library for Python with support for JSON, YAML, and TOML",
"version": "0.2.1",
"project_urls": {
"Homepage": "https://github.com/UrielCuriel/python_i18n_modern",
"Issues": "https://github.com/UrielCuriel/python_i18n_modern/issues",
"Repository": "https://github.com/UrielCuriel/python_i18n_modern"
},
"split_keywords": [
"i18n",
" internationalization",
" l10n",
" localization",
" translation"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "322f7fbe6d9e85eb5bf623269741c7659affc0644cfd4f9e950eb89e8c39a926",
"md5": "c7ca93ee147fff2795de5d6596fb0467",
"sha256": "365b382012f3aa647ee2667c7b21c135594ee2d615c11bf3b71d092271e38729"
},
"downloads": -1,
"filename": "i18n_modern-0.2.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "c7ca93ee147fff2795de5d6596fb0467",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 76348,
"upload_time": "2025-10-18T00:00:13",
"upload_time_iso_8601": "2025-10-18T00:00:13.549186Z",
"url": "https://files.pythonhosted.org/packages/32/2f/7fbe6d9e85eb5bf623269741c7659affc0644cfd4f9e950eb89e8c39a926/i18n_modern-0.2.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "9a73839cb695cae40f86ca8fbbc9d2a8266c9bdcbe9bb90e4269c0538b52fb00",
"md5": "3b5e56ddd80c734263266b7c50e7e8e8",
"sha256": "b65af66f94bdacd3b8ea2e4f1e29b0f77d8990cff0d068eb7bd98d285780c011"
},
"downloads": -1,
"filename": "i18n_modern-0.2.1.tar.gz",
"has_sig": false,
"md5_digest": "3b5e56ddd80c734263266b7c50e7e8e8",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 145975,
"upload_time": "2025-10-18T00:00:14",
"upload_time_iso_8601": "2025-10-18T00:00:14.970669Z",
"url": "https://files.pythonhosted.org/packages/9a/73/839cb695cae40f86ca8fbbc9d2a8266c9bdcbe9bb90e4269c0538b52fb00/i18n_modern-0.2.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-10-18 00:00:14",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "UrielCuriel",
"github_project": "python_i18n_modern",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "i18n_modern"
}