Locale.gettext: примеры (PYTHON)
locale.gettext(msg: str): strОбзор функции locale.gettext в Python
Функция locale.gettext() является частью модуля locale в стандартной библиотеке Python. Она предоставляет интерфейс для получения локализованных строковых сообщений на основе системных настроек локали или переопределенных параметров. Использование данной функции характерно для интернационализации (i18n) и локализации (L10n) приложений.
Функция применяется в случаях, когда программное обеспечение требует адаптации текстового контента под языковые и региональные предпочтения пользователя. Типичные сценарии включают локализацию интерфейса, форматирование дат, чисел и валют с учетом региональных стандартов.
Синтаксис и параметры
Базовый синтаксис функции: locale.gettext(message).
- message (строка, обязательный): исходное строковое сообщение на языке по умолчанию (обычно английском), которое требуется перевести. Эта строка служит ключом для поиска в файлах перевода (например, .po или .mo).
Возвращаемое значение
Функция возвращает локализованную строку, соответствующую переданному сообщению message, если перевод для текущей локали существует. В противном случае возвращается оригинальная строка message. Тип возвращаемого значения - строка (str).
Для корректной работы функции locale.gettext требуется предварительная настройка модуля locale с помощью функций locale.setlocale() и locale.bindtextdomain(). Эти вызовы устанавливают текущую локаль и указывают путь к каталогам с переводами.
Примеры применения locale.gettext
Базовый пример с установкой локали
Перед использованием gettext необходимо настроить локаль и привязать домен перевода.
import locale
import os
# Установка локали в 'ru_RU.UTF-8'
locale.setlocale(locale.LC_ALL, 'ru_RU.UTF-8')
# Привязка домена 'myapp' к каталогу с переводами
locale.bindtextdomain('myapp', os.path.join(os.path.dirname(__file__), 'locale'))
locale.textdomain('myapp')
# Пример вызова gettext
print(locale.gettext("Hello, world!"))Привет, мир!
Пример без найденного перевода
Если перевод для сообщения отсутствует, возвращается исходная строка.
import locale
locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
print(locale.gettext("Untranslated string"))Untranslated string
Использование с псевдопереводом для тестирования
Иногда используют псевдоперевод для проверки работы системы локализации.
import locale
locale.setlocale(locale.LC_ALL, 'C')
# В локали 'C' переводы не загружаются, возвращается оригинал
print(locale.gettext("Test message"))Test message
Альтернативные функции в Python
В Python для задач интернационализации доступны несколько функций и модулей со схожей функциональностью.
gettext.gettext()
Функция gettext.gettext() из одноименного модуля является более низкоуровневым аналогом. Она не зависит от системных настроек локали, требует явной установки переводов через объекты GNUTranslations. Предпочтительнее использовать при необходимости тонкого контроля над загрузкой переводов или в embedded-средах.
gettext.pgettext()
Функция gettext.pgettext(context, message) позволяет указать контекст для перевода, что полезно при наличии омонимов. Используется, когда одно исходное сообщение может иметь разные переводы в зависимости от контекста.
gettext.ngettext()
Функция gettext.ngettext(singular, plural, n) предназначена для обработки множественных чисел. Она выбирает правильную форму перевода на основе числа n. Альтернатива locale.gettext для перевода строк с учетом количества.
Babel
Сторонняя библиотека Babel предоставляет расширенные возможности интернационализации, включая извлечение строк, форматирование дат, чисел, единиц измерения. Babel предпочтительнее для сложных проектов с необходимостью форматирования множества локализуемых данных.
Аналоги функции в других языках программирования
JavaScript (i18next)
Библиотека i18next предоставляет функционал для перевода строк с поддержкой пространств имен, контекста и множественного числа.
// Установка и настройка i18next
i18next.init({
lng: 'ru',
resources: {
ru: { translation: { "Hello": "Привет" } }
}
});
console.log(i18next.t('Hello'));Привет
Java (ResourceBundle)
В Java для локализации используют класс ResourceBundle, который загружает свойства из файлов .properties на основе локали.
import java.util.ResourceBundle;
import java.util.Locale;
Locale locale = new Locale("ru", "RU");
ResourceBundle bundle = ResourceBundle.getBundle("Messages", locale);
String message = bundle.getString("hello");
System.out.println(message);Привет
PHP (gettext)
В PHP встроены функции gettext, которые работают аналогично Python, но интегрированы с веб-сервером.
setlocale(LC_ALL, 'ru_RU.UTF-8');
bindtextdomain('myapp', './locale');
textdomain('myapp');
echo gettext("Hello");Привет
C# (Resources и CultureInfo)
В .NET используют файлы ресурсов (.resx) и класс CultureInfo для управления локализацией.
System.Globalization.CultureInfo ci = new System.Globalization.CultureInfo("ru-RU");
System.Threading.Thread.CurrentThread.CurrentCulture = ci;
string message = MyApp.Resources.Strings.Hello;Привет
Golang (golang.org/x/text/message)
Пакет message из golang.org/x/text предоставляет функции для интернационализации, похожие на gettext.
import "golang.org/x/text/message"
p := message.NewPrinter(message.MatchLanguage("ru"))
p.Println("Hello")Привет
Основное отличие аналогов в других языках заключается в интеграции с экосистемой и дополнительными возможностями, такими как встроенная поддержка plural forms в JavaScript-библиотеках или автоматическое извлечение строк в Java.
Распространенные ошибки при работе с locale.gettext
Ошибка установки локали
Неправильное указание кода локали приводит к возврату исходных строк.
import locale
# Локаль 'ru_RU' может быть недоступна в системе
locale.setlocale(locale.LC_ALL, 'ru_RU')
print(locale.gettext("Hello"))Hello
Отсутствие привязки домена перевода
Без вызова locale.bindtextdomain и locale.textdomain функция не сможет найти файлы переводов.
import locale
locale.setlocale(locale.LC_ALL, 'ru_RU.UTF-8')
# Домен не привязан
print(locale.gettext("Test"))Test
Использование до настройки локали
Вызов gettext до установки локали с помощью setlocale может не дать ожидаемого результата.
import locale
print(locale.gettext("Hello")) # Локаль еще не установлена
locale.setlocale(locale.LC_ALL, 'ru_RU.UTF-8')Hello
Проблемы с кодировкой файлов перевода
Файлы .po должны быть в корректной кодировке (обычно UTF-8). Иначе возможны ошибки декодирования.
# Файл .po в кодировке Windows-1251 без указания charset
# При загрузке может возникнуть ошибка UnicodeDecodeErrorЗабытый вызов install() для gettext
При использовании модуля gettext напрямую, для замены стандартной функции _() требуется вызвать gettext.install().
import gettext
gettext.bindtextdomain('myapp', 'locale')
gettext.textdomain('myapp')
_ = gettext.gettext # Без install() функция _ не будет глобально доступна
print(_("Hello"))Изменения в функции в последних версиях Python
Функция locale.gettext остается стабильной в течение многих версий Python. Однако в модуле locale произошли изменения, влияющие на ее работу.
Python 3.11
В Python 3.11 улучшена обработка ошибок при установке локали. Функция setlocale теперь может возвращать более информативные сообщения об ошибках, что облегчает отладку проблем с gettext.
Python 3.8
В Python 3.8 добавлена поддержка локали "C.UTF-8" на некоторых платформах, что улучшает поведение locale.gettext в контейнеризованных средах, где локаль POSIX может быть недоступна.
Python 3.7
В Python 3.7 улучшена совместимость с платформами Windows, где ранее могли возникать проблемы с установкой локалей, отличных от системной.
Стоит отметить, что сам модуль gettext, на котором базируется locale.gettext, также развивается. В последних версиях улучшена поддержка формата .mo файлов и добавлены возможности для кастомизации.
Расширенные примеры использования locale.gettext
Локализация с использованием доменов
Можно использовать несколько доменов перевода в одном приложении.
import locale
import os
locale.setlocale(locale.LC_ALL, 'ru_RU.UTF-8')
# Привязка двух доменов
locale.bindtextdomain('ui', '/path/to/ui/locale')
locale.bindtextdomain('errors', '/path/to/errors/locale')
# Установка активного домена
locale.textdomain('ui')
print(locale.gettext("Save")) # Ищет в домене 'ui'
# Временное переключение домена для получения перевода ошибки
old_domain = locale.textdomain('errors')
print(locale.gettext("File not found"))
locale.textdomain(old_domain) # Возврат к предыдущему доменуСохранить Файл не найден
Динамическая смена локали в рантайме
Локаль можно менять во время выполнения программы.
import locale
def switch_locale(locale_name):
locale.setlocale(locale.LC_ALL, locale_name)
locale.bindtextdomain('myapp', 'locale')
locale.textdomain('myapp')
return locale.gettext
_ = switch_locale('ru_RU.UTF-8')
print(_("Hello"))
_ = switch_locale('de_DE.UTF-8')
print(_("Hello"))Привет Hallo
Интеграция с классами и объектами
Локализованные строки можно интегрировать в классы с помощью свойств.
import locale
locale.setlocale(locale.LC_ALL, 'ru_RU.UTF-8')
locale.bindtextdomain('myapp', 'locale')
locale.textdomain('myapp')
class LocalizedApp:
@property
def welcome(self):
return locale.gettext("Welcome to the application")
@property
def exit_message(self):
return locale.gettext("Goodbye!")
app = LocalizedApp()
print(app.welcome)
print(app.exit_message)Добро пожаловать в приложение До свидания!
Кэширование переводов для производительности
При частом вызове gettext с одинаковыми аргументами можно использовать кэширование.
import locale
from functools import lru_cache
locale.setlocale(locale.LC_ALL, 'ru_RU.UTF-8')
locale.bindtextdomain('myapp', 'locale')
locale.textdomain('myapp')
@lru_cache(maxsize=100)
def cached_gettext(msg):
return locale.gettext(msg)
# Многократный вызов с одним аргументом
for _ in range(5):
print(cached_gettext("Hello"))Привет Привет Привет Привет Привет
Использование с шаблонизаторами
Функцию можно интегрировать в шаблонизаторы, например, Jinja2.
import locale
from jinja2 import Environment
locale.setlocale(locale.LC_ALL, 'ru_RU.UTF-8')
locale.bindtextdomain('myapp', 'locale')
locale.textdomain('myapp')
env = Environment()
env.globals['_'] = locale.gettext
template = env.from_string("{{ _('Hello') }}, {{ name }}!")
print(template.render(name="Иван"))Привет, Иван!