Python: везде использовать gettext с __init__.py - PullRequest
5 голосов
/ 01 октября 2010

Я хотел бы использовать gettext через мое приложение.

Итак, я попытался поместить основы в __ init__.py так:

import gettext
_ = gettext.gettext

gettext.bindtextdomain ( 'brainz', '../datas/translations/' )
gettext.textdomain ( 'brainz' )

И я пробую простой звонок в Brainz.py:

#!/usr/bin/python

from brainz import *

##
# Main class of the game
class Brainz :

    def __init__ ( self ) :

        print _( "BrainZ" )
        print _( "There will be blood..." )
        print _( "By %s" ) % "MARTIN Damien"

Но у меня возникает следующая ошибка во время выполнения:

Traceback (most recent call last):
  File "main.py", line 8, in <module>
    Brainz ()
  File "/home/damien/Dropbox/Projets/BrainZ/brainz/Brainz.py", line 12, in __init__
    print _( "BrainZ" )
NameError: global name '_' is not defined

Поскольку я новичок в python, я не понимаю, что не так.

Не могли бы вы дать мне хорошие советы?

Спасибо

Дэмиен

Ответы [ 3 ]

5 голосов
/ 11 апреля 2012

sdolan объяснил , почему ваш код не работал, и предоставил отличное решение. Но у него есть неудобство: вы должны импортировать gettext в каждый модуль, для которого вы хотите включить переводы .

Эльф Штернберг предоставил очень удобный подход: вручную сделать gettext видимым во всем проекте. Но это выглядит немного загадочно и, по его словам, это чистое зло :). Он также предлагает, по неизвестной причине, совершенно не связанный Ugettext Django. Не нужно Django, придерживайтесь стандартного gettext lib, как вы делали раньше.

Могу ли я предложить третий, официально одобренный подход? В том же __init__.py, который вы пробовали ранее, используйте это:

import gettext
gettext.install('brainz', '../datas/translations/')

И это все! Доступность всего проекта _() доступным, не зашифрованным, элегантным и удобным способом, используя стандартный модуль gettext. Но, честно говоря, если вы посмотрите на исходный код gettext, вы увидите, что используется тот же прием, который предложил Эльф. Так что, по сути, это тоже Чистое Зло (тм). Но это прекрасно , если модуль 'brainz' используется только вашим приложением и не предназначен для импорта другими приложениями .

Если вы хотите поделиться «brainz» с другими приложениями, вы должны использовать подход sdolan: импортируйте его в каждый модуль. Но, опять же, вместо использования bindtextdomain и textdomain, как вы это сделали, я предлагаю следующее:

import gettext
t = gettext.translation('brainz', '../datas/translations/')
_ = t.ugettext

Разница заключается в использовании основанного на классах API gettext вместо API gettext GNU. Посмотрите в официальном справочнике , почему. Подход install также является частью API на основе классов.

Примечание: вы заметите, что в документах предлагается использовать pygettext вместо GNU xgettext. Не надо! Pygettext крайне устарел и не имеет нескольких функций. xgettext гораздо более мощный и гибкий, и полностью поддерживает Python.

5 голосов
/ 01 октября 2010

Импорт подстановочных знаков не импортирует ничего, начиная с подчеркивания.

Подстановочные знаки плохие, они загрязняют пространство имен и создают трудно обнаруживаемые ошибки. Кроме того, _ иногда используется для обозначения неиспользуемой переменной.

Просто сделайте импорт, где вам это нужно. Это всего одна строка, поэтому вводить ее несложно, и вы всегда можете создать фрагмент в своей IDE.

ОБНОВЛЕНИЕ: См. http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#importing, чтобы узнать больше причин не использовать подстановочные знаки.

2 голосов
/ 01 октября 2010

Это чистое зло, но оно делает то, что вы хотите. В корневом каталоге вашего проекта _init.py _ сделайте следующее:

from django.utils.translation import ugettext
import __builtin__
__builtin__.__dict__['_'] = ugettext

А теперь подчеркивание будет везде. Другие ответы имеют соответствующие предостережения; Модифицировать список встроенных в Python VM не очень приятно, и это наверняка запутает любого, кто с ним не знаком.

...