modern-i18n — это легковесная библиотека для интернационализации Python-проектов. Она позволяет легко управлять переводами, использовать параметризованные строки для форматирования текста. Подходит для небольших и крупных проектов.

Для кого это статья?
Статья предназначена для разработчиков проектов на Python, которые хотят внедрить в свой проект интернационализацию (поддержку нескольких языков).
Введение
В современных приложениях, особенно тех, что используются в международной среде, поддержка нескольких языков (интернационализация — i18n) является критически важным аспектом. Modern-i18n — это библиотека для Python, которая упрощает и делает процесс локализации более эффективным и понятным. Она предлагает удобный API, поддерживает JSON-формат для хранения переводов и обеспечивает гибкость настройки.
Почему я разработал собственный i18n?
Основные причины:
-
Упрощение работы с переводами
Многие популярные библиотеки i18n требуют сложной настройки и обладают избыточным API. Я хотел создать решение, которое будет простым, понятным и удобным для использования.
-
Минимизация зависимостей
Некоторые библиотеки i18n требуют установки дополнительных пакетов, что может усложнять развертывание. Modern-i18n работает без них.
-
Легкость и производительность
Библиотека modern-i18n не зависит от сторонних библиотек и легко интегрируется в любой проект. Она загружает только необходимые данные и использует механизм кэширования для повышения скорости работы.
-
Гибкость
Библиотека может использоваться как в чистых проектах на Python, так и с web-фреймворками (Flask, Django и др.).
-
Самостоятельность и контроль
Создавая собственную реализацию, я получил возможность полностью контролировать её поведение, улучшать её по мере необходимости и адаптировать под конкретные задачи проекта.
Установка
Для установки библиотеки воспользуйтесь пакетным менеджером pip:
pip install modern-i18n
Структура проекта
Для внедрения i18n необходимо создать в свой проект новые папки и файлы. Пример типовой структуры проекта после настройки библиотеки modern-i18n
:
project/
├── i18n/ # ? Модуль интернационализации
│ └── config.py # ? Конфигурационный файл: язык по умолчанию, путь к переводам и т.д.
│
├── locale/ # ? Директория с переводами (локализациями)
│ ├── en/ # ? Английская локаль
│ │ └── translation.json # ? Файл с переводами на английский язык
│ └── ru/ # ? Русская локаль
│ └── translation.json # ? Файл с переводами на русский язык
│
└── example.py # ? Пример использования функции перевода
Конфигурация
Все настройки библиотеки находятся в файле i18n/config.py
. Пример базовой конфигурации:
import os
from pathlib import Path
from modern_i18n.i18n import I18n
project_root = Path(__file__).resolve().parent.parent
LOCALE_PATH = os.path.join(project_root, 'locale')
config = {
'locale_path': LOCALE_PATH, # Путь к директории с переводами
'locales': ['ru', 'en'], # Список доступных языков
'default_locale': 'ru', # Язык по умолчанию
'default_encoding': 'UTF-8' # Кодировка для файлов перевода по умолчанию 'UTF-8'
}
i18n = I18n(config)
t = i18n.translate
В файле
i18n/config.py
настраиваются основные параметры: список доступных языков, язык по умолчанию, путь к директории с переводами и дополнительные опции.Все переводы хранятся в формате JSON внутри директории
locale
, где каждая локаль имеет свою собственную папку.
Формат переводов
Переводы хранятся в файлах translation.json
, где каждый ключ — это оригинальная фраза, а значение — её перевод на нужный язык.
Пример для английского языка (locale/en/translation.json
):
{
"Итого {a}+{b}={total}": "Total {a}+{b}={total}.",
"Количество языков на планете бесчисленное множество": "There are countless languages on the planet",
"Ограничение длины строки: {str:.6}": "String length limit: {str:.6}",
"Процент: {percent:.0%}": "Percentage: {percent:.0%}",
"Процент: {percent:.1%}": "Percentage: {percent:.1%}",
"Процент: {percent:.2%}": "Percentage: {percent:.2%}",
"Сегодня: {date:%A, %B %d, %Y}": "Today: {date:%A, %B %d, %Y}",
"Сегодня: {date:%d.%m.%Y}": "Today: {date:%d.%m.%Y}",
"Сегодня: {date}": "Today: {date}",
"Число с плавающей точкой: {number:.0f}": "Floating point number: {number:.0f}",
"Число с плавающей точкой: {number:.3f}": "Floating point number: {number:.3f}"
}
Пример для русского языка (locale/ru/translation.json
):
{
"Итого {a}+{b}={total}": "Итого {a}+{b}={total}.",
"Количество языков на планете бесчисленное множество": "Количество языков на планете бесчисленное множество",
"Ограничение длины строки: {str:.6}": "Ограничение длины строки: {str:.6}",
"Процент: {percent:.0%}": "Процент: {percent:.0%}",
"Процент: {percent:.1%}": "Процент: {percent:.1%}",
"Процент: {percent:.2%}": "Процент: {percent:.2%}",
"Сегодня: {date:%A, %B %d, %Y}": "Сегодня: {date:%A, %B %d, %Y}",
"Сегодня: {date:%d.%m.%Y}": "Сегодня: {date:%d.%m.%Y}",
"Сегодня: {date}": "Сегодня: {date}",
"Число с плавающей точкой: {number:.0f}": "Число с плавающей точкой: {number:.0f}",
"Число с плавающей точкой: {number:.3f}": "Число с плавающей точкой: {number:.3f}"
}
⚠️ Важно: все ключи должны быть одинаковыми во всех файлах, чтобы обеспечить корректное сопоставление.
ℹ️ По моему опыту по внедрению i18n в большие проекты, в качестве ключей рекомендую использовать те названия, которые уже есть у Вас на проекте.
Например, у Вас есть строковые переменные, которые нужно интернационализировать.
До внедрения i18n:
s = 'Количество языков на планете бесчисленное множество'
Вы просто берете эту строку и оборачиваете ее в функцию t
.
После внедрения i18n:
from i18n.config import t
s = t('Количество языков на планете бесчисленное множество', locale='en')
В результате получаете ту же читаемость кода, что и была. Плюс избавляет Вас от придумывания ключей, что сэкономит Вам много времени, особенно когда проект большой.
Использование библиотеки
После конфигурации вы можете использовать функцию t
для получения перевода.
from i18n.config import t
print(t('Количество языков на планете бесчисленное множество')) # -> Количество языков на планете бесчисленное множество
# Перевод с указанием локали
print(t('Количество языков на планете бесчисленное множество', locale='en')) # -> There are countless languages on the planet
Перевод с параметрами
print(t('Итого {a}+{b}={total}', a=5, b=10, total=15)) # -> Итого 5+10=15.
print(t('Итого {a}+{b}={total}', locale='en', a=5, b=10, total=15)) # -> Total 5+10=15.
Форматируемый перевод
Библиотека позволяет гибко форматировать строки, используя именованные аргументы, а также спецификаторы формата для чисел, строк и дат.
import datetime
# Число с плавающей точкой
print(t("Число с плавающей точкой: {number:.3f}", locale='en', number=3.14159)) # -> Floating point number: 3.142
print(t("Число с плавающей точкой: {number:.0f}", locale='en', number=3.5)) # -> Floating point number: 4
# Проценты
print(t("Процент: {percent:.2%}", locale='en', percent=0.736)) # -> Percentage: 73.60%
print(t("Процент: {percent:.1%}", locale='en', percent=0.736)) # -> Percentage: 73.6%
print(t("Процент: {percent:.0%}", locale='en', percent=0.736)) # -> Percentage: 74%
# Форматирование даты
today = datetime.date.today()
print(t("Сегодня: {date}", date=today)) # -> Сегодня: 2025-07-10
print(t("Сегодня: {date:%d.%m.%Y}", date=today)) # -> Сегодня: 10.07.2025
print(t("Сегодня: {date:%A, %B %d, %Y}", locale='en', date=today)) # -> Today: Thursday, July 10, 2025
# Ограничение длины строки
print(t("Ограничение длины строки: {str:.6}", locale='en', str="Привет мир!")) # -> String length limit: Привет
Обработка отсутствующих ключей
Если ключ не найден, библиотека выдаст предупреждение и вернёт исходную строку:
print(t('Ключ не существует')) # Warning -> Ключ не существует
Заключение
Modern-i18n — это мощная и простая в использовании библиотека для интернационализации Python-проектов. Она позволяет быстро настраивать локализацию, поддерживает работу с несколькими языками и параметризованными строками. Благодаря своей гибкости и лёгкости, она станет отличным выбором для разработчиков, которым нужно создать многоязычное приложение без лишней сложности.
Эта библиотека используется в реальных проектах и продолжает развиваться. Если вы сталкиваетесь с задачей локализации в Python-приложениях, обязательно попробуйте modern-i18n — возможно, она станет вашим идеальным выбором.
Буду рад обратной связи. В комментариях напишите, а как Вы решаете данную задачу.
Комментарии (7)
A-V-tor
10.07.2025 15:56Это ваша библиотека? Ни одной звезды, 4 коммита за все время. Вы тогда хотя бы скажите об этом, а то выглядит не очень безопасно.
Abbas_I Автор
10.07.2025 15:56Это библиотека абсолютно безопасна в использовании, в ней нет сторонних зависимостей, все решение создано на чистом python. Она разрабатывалась специально для проектов разного уровня сложности с которыми мне приходилось работать.
Tishka17
Минималистично API это, конечно, хорошо, но
Какие инструменты для переводчиков вы предлагаете?
Как происходит плурализация? (1 яблоко, 2 яблока, 5 яблок / 1 apple, 2 apples, 5 apples)
Как насчет локализации чисел? (1 000,15 vs 1,000.15)
andreymal
И падежи ещё (1 яблоком, 2 яблоками), я сейчас страдаю от их отсутствия в gettext
Tishka17
Имхо, падежи не меняются диамически, они не зависят от подставляемых данных. Вы просто формируете фразу сразу в нужном падеже. Но да, так мы ограничены в динамической сборке из кусков
andreymal
Подставляемые данные зависят от падежей. А среднестатистический англоязычный разработчик часто забывает, что в других языках падежей бывает больше чем в английском, и в итоге из какого-нибудь «%s угостил %s %d %s» мы получаем «Вася угостил Петя 1 яблоко»
Ах да, попутно и про род можно вспомнить, а то какое-нибудь «Получен 1 яблоко» тоже не круто
Abbas_I Автор
По сопровождению translation.json файлов и их наполнению я использую плагины в ide и отдельные приложения предназначенные чисто для этих целей.
Плюрализации в этой библиотеки нет, возможно в будущем я добавлю ее. В проектах 90% случаев плюрализация скорее всего Вам не понадобится. Если рассматривать пример с яблоками, можно переназвать это как: "Яблок: {n} шт."
Для плюрализации, чтобы это хорошо работало нужно учитывать большое количество факторов: род (мужской, женский, средний), число (множественное, единственное), контест в предложении, падежи, ешё это в разных языках это все по разному. В итоге Вы откажитесь от этой затеи и придете к нейтральным словам (предложениям).
По локализации чисел, валют, дат, номеров телефонов здесь я могу предложить использовать сторонние библиотеки, например locale (https://metanit.com/python/tutorial/6.3.php)