Name | magic-i18n JSON |
Version |
0.3
JSON |
| download |
home_page | None |
Summary | Text internationalization with async context magic |
upload_time | 2025-10-20 15:20:57 |
maintainer | None |
docs_url | None |
author | None |
requires_python | >=3.11 |
license | MIT License
Copyright (c) 2025 Dmitry Vlasov
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
|
keywords |
i18n
internationalization
async
contextvar
asgi
|
VCS |
 |
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
[![Version][version-image]][pypi-url]
[![Supported Python Version][py-versions-image]][pypi-url]
[![Downloads][downloads-image]][pypi-url]
[![Build Status][build-image]][build-url]
---
# Magic-i18n
Internationalization with special contextvars magic.
Key features:
- Relies on a mechanism of implicit context passing for asynchronous functions.
- Supports template formatting via %.
- Texts are defined separately from their usage location and passed as variables.
- Supports temporary (local) language overrides.
- Can be used both standalone and within ASGI applications.
- Utility for checking the correctness of texts for CICD.
Provides:
- container for text/template variations,
- language context manager,
- lazy template for partial text formatting,
- middleware for ASGI-compatible frameworks.
- checking utility.
## Install
```sh
pip install magic-i18n
```
## Declaration and basic usage
```python
from magic_i18n import Text, set_default_language, language
# setup global default language, must be called before running application
set_default_language('ru')
# Basic init without translations, fallback only
message = Text('text')
print(message) # print `text`
# Text in different languages, with default language for non-defined languages
message = Text(en='text', ru='текст')
print(message) # print `текст` (ru - default language)
# Text in different languages, with fallback for non-defined languages
message = Text('fail', en='text', ru='текст')
print(message) # print `текст` (ru - default language)
```
Context manager for temporarily changing the current language.
```python
with language('ru'):
print(message % name)
with language(language) as lang:
log.debug('Send with language %s', lang)
print(message % name)
```
Get a string in the specified language
```python
print(message | 'ru')
print(message | lang)
```
## Template formatting
Template in different languages
```python
message = Text(en='hello ${name}', ru='привет ${name}')
print(message % 'Alex')
print(message % ('Alex',))
print(message % {'name': 'Alex'})
# all prints `привет Alex` (ru - default language)
```
Partial formatting and deferred evaluation.
```python
lazy_template = Text(en='hello ${name}, open ${target}', ru='привет ${name}, открой ${target}')
print(lazy_template)
# print `привет ${name}, открой ${target}`
lazy_template % 'Alex'
print(lazy_template)
# print `привет Alex, открой ${target}`
lazy_template % 'Telegram'
print(lazy_template)
# print `привет Alex, открой Telegram`
lazy_template % {'target': 'Site'} # set or replace
print(lazy_template)
# print `привет Alex, открой Site`
lazy_template(target='Calc') # set or replace
print(lazy_template | 'en')
# print `hello Alex, open Calc`
```
## ASGI middleware
The ASGI middleware retrieves the language from the `Accept-Language` header
and sets it as the current language if it's present in the `accept_languages` option.
Options:
- `application` - wrapped ASGI application.
- `default_language` - (default: en) Used when the user's language is unknown or
unavailable. This is the default only for ASGI and does not call `set_default_language`.
- `accept_languages` - list of available languages. The `default_language` must be included
in this list.
```python
application = I18nMiddleware(
application,
default_language='en',
accept_languages=['en', 'ru'],
)
```
The header parser pattern `r'([a-zA-Z]{2}[-a-zA-Z0-9]*)'` can be modified in
`header_parser` class attribute.
```python
I18nMiddleware.header_parser = re.compile(...)
```
## Linter
Provides:
- Check for required languages
- Check that all versions of the text templates have the same arguments.
- Prohibit text duplication
- Spell check (requires pyspellchecker)
```bash
$ magic-i18n --help
...
$ magic-i18n example.lint_erorrs
Run magic-i18n linter
load [examples.lint_errors]
5 text objects found
[check-arguments] Text(asd | AD4JT53R): The `ru` arguments differ from fallback
[check-arguments] Text(asd ${a} | ADJ6CPYN): The `ru` arguments differ from fallback
[deny-doubles] Text(asd ${a} | ADJ6CPYN): Double detected
[required-languages] Text(asd проверка % & тест? | C2E2VTY): Required language(s) `en` are not provided
[required-languages] Text(asd | AD4JT53R): Required language(s) `en` are not provided
Failed with 5 errors
```
<!-- Badges -->
[pypi-url]: https://pypi.org/project/magic-i18n
[version-image]: https://img.shields.io/pypi/v/magic-i18n.svg
[py-versions-image]: https://img.shields.io/pypi/pyversions/magic-i18n.svg
[downloads-image]: https://img.shields.io/pypi/dm/magic-i18n.svg
[build-url]: https://github.com/scailer/magic-i18n/actions
[build-image]: https://github.com/scailer/magic-i18n/workflows/Tests/badge.svg
Raw data
{
"_id": null,
"home_page": null,
"name": "magic-i18n",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.11",
"maintainer_email": null,
"keywords": "i18n, internationalization, async, contextvar, asgi",
"author": null,
"author_email": "Dmitrii Vlasov <scailer@yandex.ru>",
"download_url": "https://files.pythonhosted.org/packages/cd/c6/e72e20d629efbc2eac56d45a2902c31c9313ce2060690580e030c63f6681/magic_i18n-0.3.tar.gz",
"platform": null,
"description": "[![Version][version-image]][pypi-url]\n[![Supported Python Version][py-versions-image]][pypi-url]\n[![Downloads][downloads-image]][pypi-url]\n[![Build Status][build-image]][build-url]\n\n---\n\n# Magic-i18n\n\nInternationalization with special contextvars magic.\n\n\nKey features:\n\n- Relies on a mechanism of implicit context passing for asynchronous functions.\n- Supports template formatting via %.\n- Texts are defined separately from their usage location and passed as variables.\n- Supports temporary (local) language overrides.\n- Can be used both standalone and within ASGI applications.\n- Utility for checking the correctness of texts for CICD.\n\n\nProvides:\n\n- container for text/template variations,\n- language context manager,\n- lazy template for partial text formatting,\n- middleware for ASGI-compatible frameworks.\n- checking utility.\n\n\n## Install\n\n```sh\npip install magic-i18n\n```\n\n\n## Declaration and basic usage\n\n```python\nfrom magic_i18n import Text, set_default_language, language\n\n# setup global default language, must be called before running application\nset_default_language('ru')\n\n# Basic init without translations, fallback only\nmessage = Text('text')\nprint(message) # print `text`\n\n# Text in different languages, with default language for non-defined languages\nmessage = Text(en='text', ru='\u0442\u0435\u043a\u0441\u0442')\nprint(message) # print `\u0442\u0435\u043a\u0441\u0442` (ru - default language)\n\n# Text in different languages, with fallback for non-defined languages\nmessage = Text('fail', en='text', ru='\u0442\u0435\u043a\u0441\u0442')\nprint(message) # print `\u0442\u0435\u043a\u0441\u0442` (ru - default language)\n```\n\nContext manager for temporarily changing the current language.\n\n```python\nwith language('ru'):\n print(message % name)\n\nwith language(language) as lang:\n log.debug('Send with language %s', lang)\n print(message % name)\n```\n\nGet a string in the specified language\n\n```python\nprint(message | 'ru')\nprint(message | lang)\n```\n\n## Template formatting\n\nTemplate in different languages\n\n```python\nmessage = Text(en='hello ${name}', ru='\u043f\u0440\u0438\u0432\u0435\u0442 ${name}')\n\nprint(message % 'Alex') \nprint(message % ('Alex',)) \nprint(message % {'name': 'Alex'}) \n# all prints `\u043f\u0440\u0438\u0432\u0435\u0442 Alex` (ru - default language)\n```\n\nPartial formatting and deferred evaluation.\n\n```python\nlazy_template = Text(en='hello ${name}, open ${target}', ru='\u043f\u0440\u0438\u0432\u0435\u0442 ${name}, \u043e\u0442\u043a\u0440\u043e\u0439 ${target}')\n\nprint(lazy_template)\n# print `\u043f\u0440\u0438\u0432\u0435\u0442 ${name}, \u043e\u0442\u043a\u0440\u043e\u0439 ${target}`\n\nlazy_template % 'Alex'\nprint(lazy_template)\n# print `\u043f\u0440\u0438\u0432\u0435\u0442 Alex, \u043e\u0442\u043a\u0440\u043e\u0439 ${target}`\n\nlazy_template % 'Telegram'\nprint(lazy_template)\n# print `\u043f\u0440\u0438\u0432\u0435\u0442 Alex, \u043e\u0442\u043a\u0440\u043e\u0439 Telegram`\n\nlazy_template % {'target': 'Site'} # set or replace\nprint(lazy_template)\n# print `\u043f\u0440\u0438\u0432\u0435\u0442 Alex, \u043e\u0442\u043a\u0440\u043e\u0439 Site`\n\nlazy_template(target='Calc') # set or replace\nprint(lazy_template | 'en')\n# print `hello Alex, open Calc`\n```\n\n\n## ASGI middleware\nThe ASGI middleware retrieves the language from the `Accept-Language` header \nand sets it as the current language if it's present in the `accept_languages` option.\n\nOptions:\n- `application` - wrapped ASGI application.\n- `default_language` - (default: en) Used when the user's language is unknown or \n unavailable. This is the default only for ASGI and does not call `set_default_language`.\n- `accept_languages` - list of available languages. The `default_language` must be included \n in this list.\n\n```python\napplication = I18nMiddleware(\n application,\n default_language='en',\n accept_languages=['en', 'ru'],\n)\n```\n\nThe header parser pattern `r'([a-zA-Z]{2}[-a-zA-Z0-9]*)'` can be modified in \n`header_parser` class attribute.\n\n```python\nI18nMiddleware.header_parser = re.compile(...)\n```\n\n\n## Linter\n\nProvides:\n- Check for required languages\n- Check that all versions of the text templates have the same arguments.\n- Prohibit text duplication\n- Spell check (requires pyspellchecker)\n\n```bash\n$ magic-i18n --help\n...\n\n$ magic-i18n example.lint_erorrs\nRun magic-i18n linter\n load [examples.lint_errors]\n5 text objects found\n[check-arguments] Text(asd | AD4JT53R): The `ru` arguments differ from fallback\n[check-arguments] Text(asd ${a} | ADJ6CPYN): The `ru` arguments differ from fallback\n[deny-doubles] Text(asd ${a} | ADJ6CPYN): Double detected\n[required-languages] Text(asd \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 % & \u0442\u0435\u0441\u0442? | C2E2VTY): Required language(s) `en` are not provided\n[required-languages] Text(asd | AD4JT53R): Required language(s) `en` are not provided\nFailed with 5 errors\n```\n\n\n<!-- Badges -->\n[pypi-url]: https://pypi.org/project/magic-i18n\n[version-image]: https://img.shields.io/pypi/v/magic-i18n.svg\n[py-versions-image]: https://img.shields.io/pypi/pyversions/magic-i18n.svg\n[downloads-image]: https://img.shields.io/pypi/dm/magic-i18n.svg\n[build-url]: https://github.com/scailer/magic-i18n/actions\n[build-image]: https://github.com/scailer/magic-i18n/workflows/Tests/badge.svg\n",
"bugtrack_url": null,
"license": "MIT License\n \n Copyright (c) 2025 Dmitry Vlasov\n \n Permission is hereby granted, free of charge, to any person obtaining a copy\n of this software and associated documentation files (the \"Software\"), to deal\n in the Software without restriction, including without limitation the rights\n to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n copies of the Software, and to permit persons to whom the Software is\n furnished to do so, subject to the following conditions:\n \n The above copyright notice and this permission notice shall be included in all\n copies or substantial portions of the Software.\n \n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n SOFTWARE.\n ",
"summary": "Text internationalization with async context magic",
"version": "0.3",
"project_urls": {
"Changelog": "https://github.com/scailer/magic-i18n/blob/master/CHANGELOG",
"Homepage": "https://github.com/scailer/magic-i18n",
"Repository": "https://github.com/scailer/magic-i18n.git"
},
"split_keywords": [
"i18n",
" internationalization",
" async",
" contextvar",
" asgi"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "50065e4a64456b638b738302eba5099cb6a4152bbe77876281933e140d13d575",
"md5": "d98c13d8960d759b551e449431c02977",
"sha256": "9d22f7fab8b0c7d73af9368874a94e5bd12381a381acb2c4cda9428f39f6eb5c"
},
"downloads": -1,
"filename": "magic_i18n-0.3-py3-none-any.whl",
"has_sig": false,
"md5_digest": "d98c13d8960d759b551e449431c02977",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.11",
"size": 10841,
"upload_time": "2025-10-20T15:20:56",
"upload_time_iso_8601": "2025-10-20T15:20:56.251209Z",
"url": "https://files.pythonhosted.org/packages/50/06/5e4a64456b638b738302eba5099cb6a4152bbe77876281933e140d13d575/magic_i18n-0.3-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "cdc6e72e20d629efbc2eac56d45a2902c31c9313ce2060690580e030c63f6681",
"md5": "b5945eedf87701c19245bdafe3a3db68",
"sha256": "93fe58146402b8fb69957fc2b1e4320b9ba3cbf5bd67cb6c0378930a3fc83d7a"
},
"downloads": -1,
"filename": "magic_i18n-0.3.tar.gz",
"has_sig": false,
"md5_digest": "b5945eedf87701c19245bdafe3a3db68",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.11",
"size": 17036,
"upload_time": "2025-10-20T15:20:57",
"upload_time_iso_8601": "2025-10-20T15:20:57.273089Z",
"url": "https://files.pythonhosted.org/packages/cd/c6/e72e20d629efbc2eac56d45a2902c31c9313ce2060690580e030c63f6681/magic_i18n-0.3.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-10-20 15:20:57",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "scailer",
"github_project": "magic-i18n",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "magic-i18n"
}