search

Friday, August 5, 2011

Python: Интернализация (i18n) приложения

Интернализацию приложения будем проводить с помощью GNU gettext, который в версии Python 2.7 присутствует. Цель - добавить русский язык в приложение, созданное с помощью wxPython.

Идея:
1. Строки, предназначенные для перевода необходимо пометить - в данном случае вот так _('Строка для перевода')
2. Извлечь помеченные строки в отдельный файл, который будет иметь расширение *.pot
3. Отредактировать полученный файл, вставляя переведенное значение, и сохранить его с расширением *.po
4. Скомпилировать полученный файл в файл с расширением *.mo.
5. Загрузить перевод в приложение.

Пример:
В начале, в код программы необходимо импортировать следующие модули:
import wx
import gettext
import sys, os


Затем создаем иеархию папок с переводами. Они будут иметь следующий вид:
./locale/en_US/LC_MESSAGES/
где en - язык, US - страна.

В приведенном ниже коде при старте программы будет определено местоположение пользователя и его язык по-умолчания. По полученным данным будет загружен файл перевода. При его отсутствии будут отображены символы, присутствующие в коде (_())

basepath = os.path.abspath(os.path.dirname(sys.argv[0]))
localedir = os.path.join(basepath, 'locale')
langid = wx.LANGUAGE_DEFAULT
domain = 'main'
mylocale = wx.Locale(langid)
mylocale.AddCatalogLookupPathPrefix(localedir)
mylocale.AddCatalog(domain)
mytranslation = gettext.translation(domain, localedir, [mylocale.GetCanonicalName()], fallback = True)
mytranslation.install()

wx.Frame.__init__(self, parent, id, title, wx.DefaultPosition, wx.DefaultSize)
panel = wx.Panel(self)
text = _(u'Press Me')
button = wx.Button(panel, -1, text)


Код этот можно поместить в def __init__, например.

Теперь, когда код готов, приступим к генерации файлов перевода.

Для этого, если Python у вас установлен на диске C:\, скопируйте файл с кодом (в примере main.py) в папку C:\Python27\Tools\i18n

Затем, для генерации *.pot - файла, выполните из командной строки, находясь в папке i18n:
python pygettext.py -d main -o main.pot main.py


Откройте для редактирования появившийся файл и сделайте превод и укажите кодировку:
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"


Перевод записывайте в строку с msgstr:
#: main.py:28
msgid "Press Me"
msgstr "Переведено - Нажми меня"


Отредактированный файл сохраняем как main.po.

Теперь сгенерируем *.mo - файл. Для этого в терминале выполняем:
python msgfmt.py -o main.mo main.po


Полученный файл вставляем в соответствующую директорию.

P.S. При сохранении переведенного файла использовалась программа Notepad++. Необходимо, чтобы *.po - файл был в кодировке UTF-8. Для этого необходимо зайти в Settings -> Preferences -> New Document/ Default Directory и отметить Encoding UTF-8 without BOM. Внизу появится строка ANSI as UTF-8. Если этого не сделать, компилятор может выдать сообщение об ошибке.

P.P.S. Вышеизложенное было рассмотрено на примере Linux и Eclipse. Чтобы локализацию заставить работать в Windows, необходимо во всех случаях utf-8 заменить на cp1251 (и сохранять *.po -файл также в кодировке cp1251). Таким образом, *.po файлы различны для Windows и Linux.

2 comments:

  1. ок!
    Спасибо за статью! Она помогла сгенерировать необходимые файлы, но не совсем понятно что мне с ними дальше делать.
    код скрипта (proba21.py) в директории var/www/cgi-bin/
    #!/usr/bin/python
    # -*- coding: utf-8 -*-

    import gettext
    from gettext import gettext as _
    gettext.textdomain(proba21.py)

    import i18n
    _ = i18n.language.ugettext #use ugettext instead of getttext to avoid unicode errors


    print _("Hello world")


    В этой же директории у меня находится файл proba21.mo.
    который был получен из содержания proba21.po файла
    # SOME DESCRIPTIVE TITLE.
    # Copyright (C) YEAR ORGANIZATION
    # FIRST AUTHOR , YEAR.
    #
    msgid ""
    msgstr ""
    "Project-Id-Version: PACKAGE VERSION\n"
    "POT-Creation-Date: 2013-10-21 12:35+MSK\n"
    "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
    "Last-Translator: FULL NAME \n"
    "Language-Team: LANGUAGE \n"
    "MIME-Version: 1.0\n"
    "Content-Type: text/plain; charset=utf-8\n"
    "Content-Transfer-Encoding: 8bit\n"
    "Generated-By: pygettext.py 1.5\n"


    #: proba21.py:11
    msgid "Hello world"
    msgstr "Привет Мир"
    Что мне делать, чтобы заработало всё?

    ReplyDelete
  2. Debian Squeeze у меня.
    Заранее большое спасибо!

    ReplyDelete